为什么C语言全局变量初始化元素必须是常量,而局部变量可以不是常量

简介: 为什么C语言全局变量初始化元素必须是常量,而局部变量可以不是常量

前言

(1)今天看到一个有意思的问题,在交流群中,一位网友问,全局变量为什么不能给变量。会出现initializer element is not constant报错,代码如下

#include <stdio.h>
int a = 1;
int b = a+1; //这里会报错initializer element is not constant
int main(void)
{
  printf("a = %d\r\n",a);
  printf("b = %d\r\n",b);
  return 0;
}

(2)一般来说,全局变量我们都是默认给的一个常量数字,局部变量赋值给一个变量。关于上述问题,我也表示疑惑,于是我带着疑问,开始查找资料。

#include <stdio.h>
int a = 1;
int main(void)
{
  int b = a+1;
  printf("a = %d\r\n",a);
  printf("b = %d\r\n",b);
  return 0;
}


解释

全局变量和局部变量存储位置

(1)想要弄清楚这个问题,首先,我们需要知道全局变量和局部变量存储有什么区别?想了解具体信息,请看:RAM明明断电会丢失数据,为什么初始化的全局变量存储在RAM?详细分析程序的存储;

(2)因为上面的文章篇幅比较大,所以我浓缩一下。

<1>被赋值为非0的全局变量,最终会存储在.data段。他在编译时候,会变成RW-data,他的初始值是需要存储在ROM区域的。

<2>而局部变量,并不会被编译进入单片机,也就是说,他在单片机断电状态是不占空间的。

<3>当单片机上电之后,会给全局变量在RAM中分配出一个静态数据区。同时把初值赋值到这个静态数据区的.data段。

<4>单片机上电并且开始运行程序之后,调用到了局部变量所存在的那个函数时候。单片机才会给局部变量在栈中分配空间,然后赋初值是在运行过程中,执行代码实现的。

<5>因此,我们可以得出结论。被赋初值的全局变量,初始值是静态存储。而被赋初值的局部变量,初始值是动态存储。

(4)了解了上述之后,我们就能够明白为什么局部变量赋初始值可以被通过了,因为他是动态的,所以编译器不会管他。但是为什么全局变量又不可以呢?这就涉及,静态存储的数据与编译器之间的关系了。


编译器有关

(1)我们都知道,编译器能够将C语言变成机器所能够识别的01语言。而编译器的还有一些功能,常常被我们所忽视了。

(2)为了能够让程序更加小巧精炼,编译器会帮我们处理很多事情。这就引出了一个概念,用编译器的时间换运行态的时间。

<1>编译时:您(开发人员)编译代码的时间段。

<2>运行时间:用户运行您的软件的时间段。

(3)例如下面这个简单的代码:

<1>我们能够发现int b = 2 + 3;转换称为汇编代码之后,他是直接将5传递给了b。这个就是编译器进行了运算处理,对代码进行了优化。这个叫做常量折叠。

<2>sizeof这个运算同理,编译器会直接将int是4个字节这个信息传递给变量。


(4)上述两个例子都是用编译器的时间换运行态的时间。那么讲了这么多,和全局变量初始化元素必须是常量有什么关系呢?

(5)上面说了,编译器会进行常量折叠,但是请注意,这里是常量折叠!常量折叠会将常量表达式在编译器运行时期计算出来,整型字面量、sizeof()运算符(当参数不是VLA时),枚举常量,以及各种算术、关系/比较运算符在所有操作数都是整型常量时,整个表达式都会算是整型常量表达式。


(6)但是,我们发现了没有,编译器是不会进行变量的运算的!因此,全局变量int b = a+1;这样赋初值,编译器是不会进行运算的!

总结

(1)因此,我们可以得出结论:

<1>编译器无法在编译时求得一个非常量的值,它只能在运行时通过读取变量地址来间接得到变量的值,而全局变量在编译时就必须确定其值。

<2>局部变量的初始值是不由编译器管理,他是在运行时进行的分配,因此可以初值可以赋予变量。

目录
相关文章
|
2天前
|
编译器 C语言 C++
【C语言】memset()函数(内存块初始化函数)
【C语言】memset()函数(内存块初始化函数)
27 0
|
2天前
|
程序员 编译器 C语言
C语言的程序常量
C语言的程序常量
11 0
|
2天前
|
C语言 开发者
C语言中如何精确实现数组元素的插入
C语言中如何精确实现数组元素的插入
|
2天前
|
存储 编译器 数据处理
C语言中二维数组的初始化
C语言中二维数组的初始化
17 0
|
2天前
|
存储 C语言
C语言中字符串的引用与数组元素操作
C语言中字符串的引用与数组元素操作
23 0
|
2天前
|
存储 编译器 C语言
C语言字符常量详解
C语言字符常量详解
24 0
|
2天前
|
存储 C语言
【C语言数组】创建、初始化、以及使用2
【C语言数组】创建、初始化、以及使用
|
2天前
|
存储 C语言
【C语言数组】创建、初始化、以及使用1
【C语言数组】创建、初始化、以及使用
|
2天前
|
存储 C语言
【C语言】全局变量与局部变量
【C语言】全局变量与局部变量
8 1
|
2天前
|
C语言
C语言5🔥:复合赋值,递增递减运算符,局部变量与全局变量
C语言5🔥:复合赋值,递增递减运算符,局部变量与全局变量
27 0