0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于C语言大坑你知道嘛?

Q4MP_gh_c472c21 来源:鱼鹰谈单片机 作者:鱼鹰谈单片机 2022-05-10 14:43 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在开发过程中,你是否会发出“基础不牢,地动山摇”的感慨?我相信,只要有经验的工程师,应该都有过。 鱼鹰曾经因为一个很基础的知识,差点毁了整个项目,这不是危言耸听。因为这个代码用于整个系统自检,一旦运行出错,整个系统就废了。 为了不让别人篡改鱼鹰的代码,鱼鹰设计了多套机制,其中一个就是定时检查关键代码是否已执行,如果有一次没有执行,那么系统进入异常状态,这个功能类似窗口看门狗
uint16_trun_cnt, run_cnt_next;
void function1(){dosomething;run_cnt++; // 自加,表示该函数已执行}int main(){while(1){function1();if(run_cnt!=run_cnt_next+1)//判断两个变量是否匹配{doerrorsome thing}run_cnt_next++;//这个位置也自加,表示这里已执行}}

类似流程如上,当时鱼鹰为了减少变量空间,将计数器设计成了 uint16_t 类型,导致埋下了隐患。

这个流程乍一看没有问题,因为 run_cnt比 run_cnt_next 先加,那么run_cnt_next + 1 应该等于run_cnt,如果不相等,作错误处理。

甚至短时间内运行不会有任何问题,除非 16 位溢出……

所以一个量产项目,任何一点改动,都可能需要长时间的稳定测试,只有这样才能确保系统稳定性,不能认为自己能力强,写的代码不用测试就直接合并了。

原先鱼鹰以为,这两个变量都是 16 位,那么 + 1 的结果应该也是16 位,最后比较时,也是 16 位比较,这样即使最终 16 位自加溢出了,结果也会是正确的。

if(run_cnt != run_cnt_next + 1) // 判断两个变量是否匹配{      do error some thing}

但你以为,终究是你以为。

实际上,因为你和1自加了,最终比较是按照 32 位进行比较,而 run_cnt 受到变量位数限制,始终是16位的结果(但扩展成 32 位比较,即高 16 位全是 0)

bca4b5e6-d016-11ec-bce3-dac502259ad0.png


这样就会导致在溢出时,两者是不相等的。

比如上一次run_cnt 为0xFFFF 时(受位数限制,最大只能是这个),run_cnt_next 为 0xFFFE,此次结果比较即使按 32 位比较,也是没有问题的,都是 0xFFFF。

但下一次运行时,run_cnt 自加,溢出变成 0,而run_cnt_next是 0xFFFF,再和 1 相加,因为比较会使用 32 位比较,所以此时结果是0x10000,最终导致两者不相等(0 != 0x10000)。

那么,为什么会导致上面的问题呢?这里涉及到两个 C 语言基础知识点,估计大家以前都了解过,但估计没有当回事。

1、常量默认为 int 型(但不一定是 32 bit ,和内核和编译器有关,上面的+1 就是 int 型)

2、整型提升(详细可网上查找)

因为两边的结果类型不一致(+ 1 导致右边结果成了 int 类型),所以最终按 int 型处理。最终导致溢出时,结果判断失败。

我们可以通过汇编看出一些端倪:

bcba5a9a-d016-11ec-bce3-dac502259ad0.png

我们可以看到 r0+ 1 之后,直接和 r1 比较,也就是说,结果可能超过 0xFFFF,导致出错。

那么,怎么样才可以保证结果为 16 位呢?

我们可以这样处理:

if((uint16_t)run_cnt!=(uint16_t)(run_cnt_next+1))//强制转化为16位比较{      do error some thing}

我们可通过汇编发现,多了一条 UXTH 指令,用于把 16 位结果扩展成 32 位(从这里我们也可以得出结论,结果比较总是 32 bit 比较)。

bcd775a8-d016-11ec-bce3-dac502259ad0.png

到此,分析结束!我们可以看到,为了解释这么一条简单的 C 语言语句,还是挺困难的事情。

END 审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7642

    浏览量

    144648
  • 代码
    +关注

    关注

    30

    文章

    4942

    浏览量

    73160

原文标题:这个C语言大坑,你见过没?

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    C语言特性

    1、高效性:直接操作硬件 C 语言代码的执行效率极高,这是其最为显著的优势之一。它能够直接访问硬件资源,与底层硬件进行紧密交互,充分发挥硬件的性能潜力。在嵌入式开发中,硬件资源往往十分有限,对程序
    发表于 11-24 07:01

    C语言和单片机C语言有什么差异

    语言的功能特性外,它可以很好的操作底层的硬件接口。在C语言的基础上,如果把一些单片机的端口或特殊功能寄存器加于定义,使用的时候会更加方便,写语句的时候,直接直观的编写。这样就差不多是
    发表于 11-14 07:55

    C语言的printf基本用法介绍

    个简单的例子: printf(\"C语言\"); 这个语句可以在屏幕上显示“C语言”,与puts(\"C
    发表于 11-12 07:04

    请问NANO 可以使用 C++ 11

    最近需要在GD32F450上开发项目,需要用到C++ ,那么 nano支持?如果不支持,使用完全板改基于GD的芯片进行开发?
    发表于 10-14 07:41

    知道板卡厂商参与芯片研发的α阶段意味着什么?

    大家都知道芯片很重要,但是否知道一颗芯片从设计构思到最终量产,需要经历怎样一个漫长的过程吗?
    的头像 发表于 09-24 17:08 7274次阅读
    <b class='flag-5'>你</b><b class='flag-5'>知道</b>板卡厂商参与芯片研发的α阶段意味着什么?

    MiniVC6(C语言快速部署)资料

    MiniVC6(C语言快速部署)软件,无需安装。
    发表于 09-04 16:59 0次下载

    技能+1!如何在树莓派上使用C++控制GPIO?

    在使用树莓派时,会发现Python和Scratch是许多任务(包括GPIO编程)中最常用的编程语言。但知道吗,也可以使用
    的头像 发表于 08-06 15:33 3601次阅读
    技能+1!如何在树莓派上使用<b class='flag-5'>C</b>++控制GPIO?

    单片机C语言入门指导(非常通俗易懂!)

    单片机的每一时刻的具体工作情况,但是一合上 书或者资料,自己却什么也不知道了,根本不用说自己写程序了。于是,我最终还是决定学 C51,毕竟 C51 和我们课上讲的 C
    发表于 06-16 16:32

    主流的 MCU 开发语言为什么是 C 而不是 C++?

    在单片机的地界儿里,C语言稳坐中军帐,C++想分杯羹?难喽。咱电子工程师天天跟那针尖大的内存空间较劲,C++那些花里胡哨的玩意儿,在这儿真玩不转。先说内存这道坎儿。您当stm32f4的
    的头像 发表于 05-21 10:33 782次阅读
    主流的 MCU 开发<b class='flag-5'>语言</b>为什么是 <b class='flag-5'>C</b> 而不是 <b class='flag-5'>C</b>++?

    单片机c语言编程实例大全

    单片机c语言编程实例大全_18
    发表于 04-30 16:11 6次下载

    深入理解C语言C语言循环控制

    C语言编程中,循环结构是至关重要的,它可以让程序重复执行特定的代码块,从而提高编程效率。然而,为了避免程序进入无限循环,C语言提供了多种循环控制语句,如break、continue和
    的头像 发表于 04-29 18:49 1744次阅读
    深入理解<b class='flag-5'>C</b><b class='flag-5'>语言</b>:<b class='flag-5'>C</b><b class='flag-5'>语言</b>循环控制

    C语言的历史及程序介绍

    电子发烧友网站提供《C语言的历史及程序介绍.pdf》资料免费下载
    发表于 04-09 16:10 0次下载

    树莓派最强大的应用商店,知道

    Pi-Apps——RaspberryPi最强大的应用商店不久前,我获得了我的第一台RaspberryPi。和大多数从Windows转移到Linux(特别是RaspberryPi用户)的用户一样,我被这些问题困扰得快要疯了:如何在我的RaspberryPi上安装表情符号字体?为什么Discord不支持ARM架构?内置的截图工具真的很差劲…我可以在哪里安装Zoo
    的头像 发表于 03-25 09:44 539次阅读
    树莓派最强大的应用商店,<b class='flag-5'>你</b><b class='flag-5'>知道</b><b class='flag-5'>嘛</b>?

    51单片机C语言学习笔记

    c51语言快速入门
    发表于 03-24 14:04 3次下载

    为什么学了C语言,却写不出像样的项目?

    在学习编程的路上,C语言几乎是每个程序员的“必修课”。不管你是打算从事嵌入式开发、系统编程,还是想要深入理解操作系统的底层原理,C语言都是一块重要的基石。然而许多人在学习
    的头像 发表于 03-14 17:37 688次阅读
    为什么学了<b class='flag-5'>C</b><b class='flag-5'>语言</b>,却写不出像样的项目?