前言
此前写了一个C51的程序,在函数中定义了一个局部变量,然后怎么都编译不通过,报错显示我定义的变量没有定义,我一开始以为是我其他部分的程序有问题,但是反复找了半天,都没找到,最后无意间看到一个资源描述下面的几行字,试了一下才真正找到原因所在。
问题描述
因为一个函数里面需要用到for循环,然后我定义一个顺序变量j
,由于此前的经验,我了解到在Keil_C51里面不能在for循环里面定义变量,因此我选择在外面定义变量,但是仍然报错,显示我定义的j
没有定义。
问题解决
无意间看到一句话
在C++中变量的定义可以在用到的时候再定义,因此可以在for循环里面定义,但是C语言必须在函数体的开头定义变量
我一开始是不信的,这不是扯淡吗,咱也不是刚写C语言,咋不记得有这条破规矩?但是很快就被打脸了,当我把那句uchar j;
移到函数开头时,还真编译通过了。。。。
于是我开始查找资料,最后发现问题出在Keil本身上,因为Keil_C51支持的C标准还是20多年前的C89,而C89要求函数中的局部变量必须定义在函数的开头。然后我就去找如何把Keil_C51的C标准给“更新一下”,但是很遗憾,Keil_ARM是可以把编译器的C标准设置为C99的,但是Keil_C51不行。既然没办法改变,那就只能适应一下喽,但是为了之后尽量不踩坑,就想着把类似的坑全部找出来,于是就去网上查找C89标准和Keil_C51编译器使用需要注意的事项,记录了一些资料。
资料汇总
- Keil C51 vs 标准C - CSDN
- C99相比C89新增内容 - CSDN
- Keil C51单片机中变量的使用方法解析 - 电子发烧友
- 关于单片机编译器中对函数中局部变量的处理 - 51黑电子论坛
- Keil C51 编译器用户手册 中文版
- Keil_ARM配置C99 - CSDN
- 判断编译器支持的C/C++版本 - CSDN
- Keil中C51编程注意要点
- C语言标准 - CSDN
综上所述,可以发现似乎Keil_C51的编译器的C标准也不是完整的C89,因为C89甚至不支持 // 的注释符,所以建议使用的时候可以多找资料,然后多参考那本Keil_C51编译器的用户手册,有问题解决问题,再记录,这样问题肯定是会越来越少的。
补充 //2022.2.13
在Keil_ARM中有时候也会出现类似问题,而且会报错:User\main.c(22): error: #268: declaration may not appear after executable statement in block,表示变量定义前不能出现可执行语句,这点也是因为Keil默认的编译器是C89,需要在项目管理中设置为C99标准,再次编译,报错即消失。