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

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

3天内不再提示

关于 函数体内局部变量定义的位置

黄工的嵌入式技术圈 来源:网站整理 2020-03-14 11:43 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

前面有小伙伴问了这样一个问题:

我将EWIAR中的一个函数拷贝到MDK-ARM中之后,发现编译出错了。为什么在EWARM中可以编译通过,但在MDK-ARM中会出错呢?

我一看代码,基本上判断问题大概出在什么位置。经过进一步分析得出错误原因:就是函数里面局部变量定义的位置不对导致的错误。

针对上面的问题,这个问题大家可能在实际项目中不常见,但牵涉的知识也有必要向大家分享。

函数中变量的定义位置

大家先看下代码中变量a、b、c、d定义的位置:

void Test(void)

{

char a;

printf("a = %d\n", a);

char b;

printf("b = %d\n", b);

for(char c = 0;c < 10; c++)

{

char d;

printf("c = %d\n", c);

printf("d = %d\n", d);

}

}

以上变量定义位置,相信很多人都看到过,有些朋友在实际编程中也常这么定义在这些位置。

上面这段代码C编译器编译会错吗?

答案:按照C89标准编译就会出错;按照C99标准编译就不会出错。

变量定义位置的区别

相信很多朋友在大学的时候都学过C和C++,学过C++的朋友都知道,上面那段代码变量定义的位置是很合理的。

但不知道大家了解过C89和C99的区别,区别的内容还是有很多,针对本文说下定义变量位置的区别。

C89标准是不允许在函数中随便位置声明变量,C语言中的变量声明不能放在任何可执行语句之后,只允许在函数(可执行语句)的开始处。如上一段代码,需要在【printf("a = %d\n", a);】这条语句之前。

C99及C++放松了限制,允许在函数体内任意位置声明变量。C99新的标准满足了在函数体内定义变量立马就使用的功能。但是,也要注意变量的作用域。如下面代码,红色的语句就会出错。

void Test(void)

{

for(char c = 0; c < 10; c++)

{

printf("c = %d\n", c);

}

printf("c = %d\n", c);

}

MDK-ARM和EWARM中C99的配置

文章开篇说的问题,就是出在IDE的配置上。EWARM工程默认是支持C99标准的,而MDK-ARM工程默认是不支持C99标准的。所以说,将一个支持C99的标准的代码拷贝到不支持C99标准的环境中,编译就会因为代码而出错。

MDK-ARM和EWARM只需要修改一下配置就可以支持C99标准,详情见下面:

1.MDK-ARM的配置

Project -> Options for Target -> C/C++ 勾选上“C99 Mode”即可。

2.EWARM的配置

Project -> Options -> C/C++ Compiler -> Language 1 选中上“C99”即可。

关于变量定义的位置也有很多争议:有的人说为了兼容C89标准,都统一写在可执行语句前面;有的人则喜欢后面C99标准规定的,这种比较随性,随定随用。我也没有什么好的建议,看个人吧。

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

    关注

    6

    文章

    361

    浏览量

    43382
  • 编译器
    +关注

    关注

    1

    文章

    1672

    浏览量

    51889
  • MDK
    MDK
    +关注

    关注

    4

    文章

    211

    浏览量

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    飞凌嵌入式ElfBoard-环境变量之获取环境变量

    所有符合标准的C语言编译器和平台。原型 3 提供了参数用来获取环境变量,这并不是标准C的main函数定义,不过有些系统可以使用它来接收环境变量(如Linux)。在类Unix操作系统(如
    发表于 03-13 08:50

    如何规范用、但不滥用局部变量(Local Variable)

    局部变量当成“共享内存的快捷通道”,它确实方便,但代价是:数据流变暗、可读性下降、容易引入竞态(race condition)。 适用场景(更“合理”的用法) 只读:多个位置需要读取同一个
    发表于 02-04 08:42

    容易造成单片机内存溢出的几个陷阱介绍

    访问的故障了。 栈区:根据上面Demo程序写的我们知道局部变量是存在于“栈区”的,所以一般我们的局部变量通常不要定义的太大,尤其是一些数组变量,如果说非常大,就会占用非常大的栈区空间,
    发表于 01-23 07:25

    堆栈的原理揭秘

    。 3. 堆栈的功能是怎么实现的?说的那么玄乎,堆栈和局部变量到底是怎么减少内存占用的呢? 3.1 软件的角度:从功能实现的角度讲,函数实参和局部变量其实都可以用全局变量来实现。 但
    发表于 01-23 07:08

    值传递、指针传递、引用传递介绍

    进行操作,也就是说,即使形参的值发生改变,实参的值也完全不受影响。   2、指针传递:指针传递其实是值传递的一种,它传递的是地址。值传递过程中,被调函数的形参作为被调函数局部变量来处理,即在
    发表于 01-21 06:48

    C语言编程-局部性原理

    循环迭代中被引用一次,对于 sum 来说,有好的时间局部性。另外,sum 为标量,没有空间局部性。 向量 v 的元素是被顺序读取的,按照它们存储在内存中的顺序一个接一个。对于变量 v ,函数
    发表于 01-07 06:01

    嵌入式C语言中各变量存储位置

    存的了解比较精准。经常需要操作的内存可分为以下几个类别: 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区
    发表于 12-25 07:54

    C语言全局变量重点使用

    重要的循环中我们不建议使用全局变量。 如果函数过多的使用全局变量,比较好的做法是拷贝全局变量的值到局部变量, 这样它才可以存放在寄存器。这
    发表于 12-12 06:58

    三种类型内存的使用

    自动存储:用于保存局部变量。当函数被调用时,就会创建一个新的自动存储区域,并在函数返回结果时删除。只有返回值会被保留,并被复制到调用它的函数的自动存储中。这意味着,返回一个指向
    发表于 12-12 06:43

    使用setjmp及longjmp函数处理异常

    // 定义一个全局的env变量 jmp_buf env; // 定义一个可能发生错误的函数 void foo(int x) { // 如果x为0,则发生除零错误,跳转到env
    发表于 12-11 08:00

    第7章 变量进阶与点阵LED(7.1 7.2)

    知识——变量的作用域和存储类别。 7.1变量的作用域 所谓的作用域就是指变量起作用的范围,也是变量的有效范围。变量按他的作用域可以分为
    的头像 发表于 12-10 16:25 482次阅读

    Stack栈到底用来干嘛的呢?

    Stack_Size就是栈大小,0x00000400就是代表有1K(0x400/1024)的大小。 那这个栈到底用来干嘛的呢? 比如说我们函数的形参、以及函数定义局部变量就是存储在
    发表于 12-01 08:04

    常用变量的介绍

    extern:用在全局变量上表示该变量在其他文件中已经定义;用在函数上作用同全局变量; static:用在全局
    发表于 11-21 07:05

    C语言开发单片机为什么大多数都采用全局变量的形式?

    单片机的芯片资源从来都是 “精打细算” 的级别,CPU 主频普遍不高,RAM 总容量本就紧张,分给栈空间的更是少得可怜。要是像普通软件那样,依赖函数返回值传递数据、频繁用局部变量周转,一来二去占用
    的头像 发表于 11-12 14:29 544次阅读
    C语言开发单片机为什么大多数都采用全局<b class='flag-5'>变量</b>的形式?

    按照芯来文档设置可以通过segger IDE debug了,但是没法看全局或者局部变量值,怎么解决?

    如题,按照芯来文档设置可以通过segger IDE debug了,但是没法看全局或者局部变量值,很麻烦。有遇到过解决了的吗?
    发表于 10-20 09:20