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

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

3天内不再提示

C语言语句简析

大鱼机器人 来源:鱼鹰谈单片机 2023-01-16 16:47 次阅读

开发过程中,你是否会发出“基础不牢,地动山摇”的感慨,我相信,只要有经验的工程师,应该都有过。

鱼鹰曾经因为一个很基础的知识,差点毁了整个项目,这不是危言耸听。

因为这个代码用于整个系统自检,一旦运行出错,整个系统就废了。

为了不让别人篡改鱼鹰的代码,鱼鹰设计了多套机制,其中一个就是定时检查关键代码是否已执行,如果有一次没有执行,那么系统进入异常状态,这个功能类似窗口看门狗

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)

9f6664f4-9567-11ed-bfe3-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 型处理。

最终导致溢出时,结果判断失败。 我们可以通过汇编看出一些端倪:

9f770ba6-9567-11ed-bfe3-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 比较)。

9f83bdec-9567-11ed-bfe3-dac502259ad0.png

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





审核编辑:刘清

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

    关注

    10

    文章

    541

    浏览量

    70256
  • 计数器
    +关注

    关注

    32

    文章

    2123

    浏览量

    92984
  • C语言
    +关注

    关注

    180

    文章

    7530

    浏览量

    128749

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

文章出处:【微信号:All_best_xiaolong,微信公众号:大鱼机器人】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请问下面的C语言语句表达什么意思?

    下面的C语言语句表达什么意思??
    发表于 11-01 04:14

    C语言语句的规则函数

    的,而C语言语句的规则函数返回的数据类型+函数名+参数+函数主体所以这几行代码也就不难理解了。该函数类型是void型,函数名称是Delay,_IO是类型修饰符,指的是单片机的静态IO口;uint_32_t是指32位的无符号整形变量;由for循环构成了函数的主体,意思是32
    发表于 07-14 08:13

    C语言入门C语言语句的更换技巧

    C语言中有很多条语句, 在我们以后接触到的程序中无非只有5条语句,而像do while和switch这样的语句并不常用,就只剩下if、for和while
    发表于 04-28 14:57 123次下载

    汇编语言学习课件_汇编语言程序组织

    第四章 汇编语言程序组织 4.1 汇编语言语句格式 4.2 汇编语言源程序结构 4.3 常用伪指令 4.4 汇编语言操作符 4.5 汇编
    发表于 12-31 10:41 0次下载

    STC单片机C语言程序设计 第11章 STC单片机C语言描述语句

    详细介绍了在STC单片机中各类C语言语句的使用情况,对于初学者有较大的帮助,感兴趣的小伙伴们可以看看。
    发表于 07-29 17:46 12次下载

    ARM汇编程序设计之汇编语言文件格式

    10.3.1 ARM汇编语言语句格式 ARM(Thumb)汇编语法语句格式如下所示。 {symbol}{instruction|directive|pseudo-instruction
    发表于 10-19 10:14 7次下载

    typedef和define的介绍及本质区别

    在计算机编程语言中用来声明自定义数据类型,配合各种原有数据类型来达到简化编程的目的的类型定义关键字。 # define 是预处理指令。下面让我们一起来看。 typedef是C语言语句,其功能是用户为已有
    发表于 04-14 07:31 4929次阅读

    嵌入式系统原理及应用教程之ARM汇编语言程序设计的详细资料说明

    本文档的主要内容详细介绍的是嵌入式系统原理及应用教程之ARM汇编语言程序设计的详细资料说明包括了:1.伪操作和伪指令 ,2.ARM汇编语言语句格式,3.ARM汇编语言的程序格式,4.相关的程序示例
    发表于 03-20 10:26 10次下载
    嵌入式系统原理及应用教程之ARM汇编<b class='flag-5'>语言</b>程序设计的详细资料说明

    C语言的if条件语句演示实例和proteus仿真图

    1、一个完整的C语言程序是由若干条语句按一定的方式组合而成的。按C语言语句执行方式的不同,C程序可分为以下三种:顺序结构、选择结构、循环结构。
    发表于 07-10 17:40 0次下载
    C<b class='flag-5'>语言</b>的if条件<b class='flag-5'>语句</b>演示实例和proteus仿真图

    有关单片机的汇编语言程序设计教程资料免费下载

    本文档的主要内容详细介绍的是有关单片机的汇编语言程序设计教程资料免费下载包括了:1.汇编语言语句格式,2.汇编语言程序设计,3.程序设计举例,4.Keil C51的应用。
    发表于 05-20 08:00 11次下载
    有关单片机的汇编<b class='flag-5'>语言</b>程序设计教程资料免费下载

    嵌入式SQL语句

    为了区分SQL语句与主语言语句,所有SQL 语句必须加前缀EXEC SQL处理过程:含嵌入式SQL语句的主语言程序预编译程序转换嵌入式SQL
    发表于 10-21 11:51 4次下载
    嵌入式SQL<b class='flag-5'>语句</b>

    单片机中常用的C语言语句合集

    单片机中常用的C语言语句合集
    发表于 01-12 09:24 45次下载

    关于单片机中简单的时延程序void Delay(__IO uint32_t nCount)

    编程的,而C语言语句的规则函数返回的数据类型+函数名+参数+函数主体所以这几行代码也就不难理解了。该函数类型是void型,函数名称是Delay,_IO是类型修饰符,指的是单片机的静态IO口;uint_32_t是指32位的无符号整形变量;由for循环构成了函数的主体,意思是32位的非负int型数据
    发表于 01-13 15:15 3次下载
    关于单片机中简单的时延程序void Delay(__IO uint32_t nCount)

    C语言_语句与位运算基本练习

    总结C语言语句的几个基本练习题,计算素数、排序、求偶数和、可逆素数、水仙花数、交换大小写、交换变量的值、位运算、语法特性等知识点。
    的头像 发表于 08-14 09:46 736次阅读

    C语言语句的作用和分类

    赋值表达式 * 由赋值运算符将一个变量和一个表达式连接起来的式子。
    的头像 发表于 03-09 10:51 444次阅读