如下函数:居然调用两次打印出来的值分别是1和2,非常不好理解
如果按照C PRIMER PLUS说的这样的变量是在编译的时候初始化的,
实在令人难以理解,编译只是生成了可执行文件而已
何来在内存里分配了空间并赋值?
int f (void)
{
static int mm=1;
mm++;
printf(“%d\n”,mm);
}
可执行程序中有个数据段,编译器将值填进去,运行的时候mm直接读取数据段中的值即可。
2)有的变量是,在编译时候确定的,在函数执行的时候,才初始化的。
3)比较特殊的还有,有的变量,只是在编译的时候,给出初始化代码,并没有确定初始化为什么值,在运行时才初始化
例如
int a =fun();
这个值,可以有这么几种方式给出
1)直接写到 可执行代码文件中,或者存储在磁盘某个(些)扇区中
1.1) 烧写到 ROM 或者flash 等可执行非易失性存储器中。
1.2)引导程序,加载操作系统的时候,把磁盘文件。或者扇区中的数据代码,加载到某块内存。
1.3)操作系统加载程序的时候,直接根据文件中的数据在内存中准备好这些数据,然后启动应用程序开始执行。
2) 运行时加载,或者初始化
2.1) 某些数据可以直接嵌入指令作为立即数,也可以作为指令的其他部分,总之变成指令的一部分了,不是独立的数据了
2.2)先存放在数据区,运行时加载(复制)初始化。 有单独的数据存在。
2.3)调用函数初始化,这个是比较特殊的。不能优化掉的话,只能运行时加载,编译时不能确定初始化为什么值。
包括用构造函数初始化,以及动态分配内存初始化指针。
2.4)用变量初始化
除了2.3)2.4)比较特殊外,所有的初始化方式,都可以在编译时候决定初始化成什么样子
所有这些初始化方式,编译器都可以确定下来
首先,你所说的,是业界流行的做法,但流行不代表就是确凿证据。人人都走阳关大道和捷径,但驴友就喜欢走没有路的偏僻丛林,你说不行?如果编译器只在EXE里为n保留一个位置,然后在程序开始执行的时候才用mov指针加一个立即数将100写到n对应的存储单元,难道不行?
其次,初始化这个词本身就没找到完整的定义,讨论起来自然各说各的。就像你说的,整个数据段加载到内存,这个覆盖内存原来东西的操作,不能叫初始化?
最后,n=n++不是一个有确定行为的表达式,赵老师会让你看置顶帖的。
int f (void) { static int mm=1; mm++; printf("%d\n",mm); }
可以理解为:
int mm=1; int f (void) { mm++; printf("%d\n",mm); }
且 mm 仅在函数 f 内可见