高手过招:请教:变量到底是在编译的时候初始化的,还是在运行的时候初始化的?

computer science 专栏收录该内容
17 篇文章 0 订阅

请教:变量到底是在编译的时候初始化的,还是在运行的时候初始化的? [问题点数:40分,结帖人learnc2015]

https://bbs.csdn.net/topics/391832733

learnc2015

Bbs1

结帖率 62.5%

变量到底是在编译的时候初始化的,还是在运行的时候初始化的?
如下函数:居然调用两次打印出来的值分别是1和2,非常不好理解
如果按照C PRIMER PLUS说的这样的变量是在编译的时候初始化的,
实在令人难以理解,编译只是生成了可执行文件而已
何来在内存里分配了空间并赋值?

int f (void)
{
  static int mm=1;
  mm++;
  printf("%d\n",mm);
}

0 2015-09-21 13:23:12

回复数 48 只看楼主 引用 举报 楼主

珍惜生命远离CPP

Bbs9

BlankBlankBlankBlank

简单的说
可执行程序中有个数据段,编译器将值填进去,运行的时候mm直接读取数据段中的值即可。
 

2 2015-09-21 13:28:53

只看TA 引用 举报 #1    得分 2

二班的码农

Bbs5

BlankBlank

引用 楼主 learnc2015 的回复:

变量到底是在编译的时候初始化的,还是在运行的时候初始化的?
如下函数:居然调用两次打印出来的值分别是1和2,非常不好理解
如果按照C PRIMER PLUS说的这样的变量是在编译的时候初始化的,
实在令人难以理解,编译只是生成了可执行文件而已
何来在内存里分配了空间并赋值?

int f (void)
{
  static int mm=1;
  mm++;
  printf("%d\n",mm);
}



打印出的值分别为1和2,是因为mm为静态变量,静态变量具有全局特性,在整个程序中,只被初始化一次,在编译时就已经确定其初始值

0 2015-09-21 13:50:41

只看TA 引用 举报 #2    得分 2

learnc2015

Bbs1

引用 1 楼 akirya 的回复:

简单的说
可执行程序中有个数据段,编译器将值填进去,运行的时候mm直接读取数据段中的值即可。


这么说的话,对于函数内的 static 变量,static int a=1;,第二次调用的时候根本就不会执行?
这是多么的迷惑人啊!!BUG就是这么造成的

引用 2 楼 ant2012 的回复:

Quote: 引用 楼主 learnc2015 的回复:

变量到底是在编译的时候初始化的,还是在运行的时候初始化的?
如下函数:居然调用两次打印出来的值分别是1和2,非常不好理解
如果按照C PRIMER PLUS说的这样的变量是在编译的时候初始化的,
实在令人难以理解,编译只是生成了可执行文件而已
何来在内存里分配了空间并赋值?

int f (void)
{
  static int mm=1;
  mm++;
  printf("%d\n",mm);
}


打印出的值分别为1和2,是因为mm为静态变量,静态变量具有全局特性,在整个程序中,只被初始化一次,在编译时就已经确定其初始值


这么说的话,对于函数内的 static 变量,static int a=1;,第二次调用的时候根本就不会执行?
这是多么的迷惑人啊!!BUG就是这么造成的

0 2015-09-21 13:54:36

只看TA 引用 举报 #3    得分 0

牧野狂少

Bbs1

引用 2 楼 ant2012 的回复:

Quote: 引用 楼主 learnc2015 的回复:

变量到底是在编译的时候初始化的,还是在运行的时候初始化的?
如下函数:居然调用两次打印出来的值分别是1和2,非常不好理解
如果按照C PRIMER PLUS说的这样的变量是在编译的时候初始化的,
实在令人难以理解,编译只是生成了可执行文件而已
何来在内存里分配了空间并赋值?

int f (void)
{
  static int mm=1;
  mm++;
  printf("%d\n",mm);
}


打印出的值分别为1和2,是因为mm为静态变量,静态变量具有全局特性,在整个程序中,只被初始化一次,在编译时就已经确定其初始值


+1,楼主应该学习下静态变量和普通变量的区别

0 2015-09-21 14:00:27

只看TA 引用 举报 #4    得分 2

赵4老师

Bbs12

BlankBlankBlankBlank

有的变量是在编译的时候初始化的,有的变量是在运行的时候初始化的。

1 2015-09-21 14:05:12

只看TA 引用 举报 #5    得分 2

lm_whales

Bbs8

BlankBlank

1)有的变量是在编译时候确定的,但是加载的时候(这算是运行时不?此时程序还没有开始运行)初始化的

2)有的变量是,在编译时候确定的,在函数执行的时候,才初始化的。
3)比较特殊的还有,有的变量,只是在编译的时候,给出初始化代码,并没有确定初始化为什么值,在运行时才初始化
例如
 int a =fun(); 

1 2015-09-21 14:11:58

只看TA 引用 举报 #6    得分 2

赵4老师

Bbs12

BlankBlankBlankBlank

《深度探索C++对象模型》
《C++反汇编与逆向分析技术揭秘》

0 2015-09-21 14:14:35

只看TA 引用 举报 #7    得分 0

均陵鼠侠

Bbs5

Blank

编译的时候还能够初始化,头一次听说。你能想像,房子还没开始盖,就已经开始装修了。
静态存储期的对象(也就是你们所说的静态变量)在程序启动时初始化,不管它在哪里声明和定义,其生存期和整个程序的执行时间相同;
对于具有自动存储期的对象(也就是你们所说的局部变量)来说,如果是非变长数组且它的声明中带有初始化器,则在程序的执行到达其所在的声明处时初始化。

楼主的例子中,mm具有静态存储期,故在程序启动时初始化。mm声明的位置和它的初始化时间无关。

1 2015-09-21 14:30:32

只看TA 引用 举报 #8    得分 0

均陵鼠侠

Bbs5

Blank

引用 5 楼 zhao4zhong1 的回复:

有的变量是在编译的时候初始化的,有的变量是在运行的时候初始化的。



引用 7 楼 zhao4zhong1 的回复:

《深度探索C++对象模型》
《C++反汇编与逆向分析技术揭秘》



这都搞不清楚,还模型、揭秘呢。看了也白看。

0 2015-09-21 14:30:10

只看TA 引用 举报 #9    得分 0

二班的码农

Bbs5

BlankBlank

引用 3 楼 learnc2015 的回复:

Quote: 引用 1 楼 akirya 的回复:

简单的说
可执行程序中有个数据段,编译器将值填进去,运行的时候mm直接读取数据段中的值即可。

这么说的话,对于函数内的 static 变量,static int a=1;,第二次调用的时候根本就不会执行?
这是多么的迷惑人啊!!BUG就是这么造成的

引用 2 楼 ant2012 的回复:
Quote: 引用 楼主 learnc2015 的回复:

变量到底是在编译的时候初始化的,还是在运行的时候初始化的?
如下函数:居然调用两次打印出来的值分别是1和2,非常不好理解
如果按照C PRIMER PLUS说的这样的变量是在编译的时候初始化的,
实在令人难以理解,编译只是生成了可执行文件而已
何来在内存里分配了空间并赋值?

int f (void)
{
  static int mm=1;
  mm++;
  printf("%d\n",mm);
}


打印出的值分别为1和2,是因为mm为静态变量,静态变量具有全局特性,在整个程序中,只被初始化一次,在编译时就已经确定其初始值

这么说的话,对于函数内的 static 变量,static int a=1;,第二次调用的时候根本就不会执行?
这是多么的迷惑人啊!!BUG就是这么造成的



对,第二次调用时static int a=1不会执行

0 2015-09-21 14:36:06

只看TA 引用 举报 #10    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?

0 2015-09-21 14:53:59

只看TA 引用 举报 #11    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

别跟我说const变量不是变量。
别跟我说被编译器优化为常量的取值不变的变量不是变量。

理解和讨论之前请先学会如何观察

计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!

单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

1 2015-09-21 14:56:16

只看TA 引用 举报 #12    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

有些模块化的房子还真是先装修好再盖的。

0 2015-09-21 14:57:27

只看TA 引用 举报 #13    得分 0

均陵鼠侠

Bbs5

Blank

引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?



1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!

0 2015-09-21 15:07:21

只看TA 引用 举报 #14    得分 0

learnc2015

Bbs1

引用 14 楼 sholber 的回复:

Quote: 引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?


1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!


请皇上明示

0 2015-09-21 15:18:05

只看TA 引用 举报 #15    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

为什么不自己研读gcc源代码中相关片断呢?

0 2015-09-21 15:45:23

只看TA 引用 举报 #16    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

《The Intel 64 and IA-32 Architectures Software Developer's Manual》

0 2015-09-21 15:44:55

只看TA 引用 举报 #17    得分 0

均陵鼠侠

Bbs5

Blank

引用 17 楼 zhao4zhong1 的回复:

《The Intel 64 and IA-32 Architectures Software Developer's Manual》



你没搞清楚立即数和常量的区别。再说,常量这个词不是哪个领域都是一个意思滴。

0 2015-09-21 17:05:18

只看TA 引用 举报 #18    得分 0

mewiteor

Bbs5

楼主可以研究一下pe文件结构(windows)或elf文件结构(linux),如果是常量表达式初始化的话,用十六进制编辑器打开可执行文件是可以找到初始化的值,这段数据会被直接加载到内存,成为已初始化的变量。

0 2015-09-21 17:50:44

只看TA 引用 举报 #19    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

别跟我说被编译器优化为立即数的取值不变的变量不是变量。

0 2015-09-21 17:51:58

只看TA 引用 举报 #20    得分 15

yajuie

Bbs2

高手辨论,此帖必火,留名

0 2015-09-21 19:30:05

只看TA 引用 举报 #21    得分 0

learnc2015

Bbs1

引用 20 楼 zhao4zhong1 的回复:

别跟我说被编译器优化为立即数的取值不变的变量不是变量。


看来皇上错了?

0 2015-09-21 22:15:36

只看TA 引用 举报 #22    得分 0

www_adintr_com

Bbs8

BlankBlankBlankBlank

引用 8 楼 sholber 的回复:

编译的时候还能够初始化,头一次听说。你能想像,房子还没开始盖,就已经开始装修了。
静态存储期的对象(也就是你们所说的静态变量)在程序启动时初始化,不管它在哪里声明和定义,其生存期和整个程序的执行时间相同;
对于具有自动存储期的对象(也就是你们所说的局部变量)来说,如果是非变长数组且它的声明中带有初始化器,则在程序的执行到达其所在的声明处时初始化。

楼主的例子中,mm具有静态存储期,故在程序启动时初始化。mm声明的位置和它的初始化时间无关。



引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?



引用 14 楼 sholber 的回复:

Quote: 引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?


1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!



PE 文件中有一个已初始化的数据段,里面的内容是编译器编译的时候把内容写进去的。 程序运行的时候,操作系统直接将文件中对应的位置映射到一个内存地址上。当程序中的代码第一次访问这个地址的时候,操作系统把文件内容加载到物理内存中,并且建立内存地址和物理地址的映射。 
对程序中的代码来说,它表现出来就是没有向这个地址写入内容就直接读取了。

这个对应汇编语言中的类似这样的数据定义:

DB   'ASCLL'
DW  0012H,0210H

这里的 db, dw 并不对应机器指令,不会生成程序代码,只是指示汇编器如何生成一个数据段,并指明它的初始内容。

这种形式指定的初始值,应该就是各位所说的编译期初始化。

当然,编译期是没法分配内存,初始化内存这些的。但是,可以通过生成指定格式的 exe 文件来告诉操作系统,让操作系统在运行程序的代码之前,按照编译器的要求来初始化内存。


汇编指令中的立即数,也就是常量,这种东西根本就不是一个变量,和变量的初始化扯不上关系。如果是用指令中的立即数来初始的变量,那这个变量肯定是运行期才初始化的了。

0 2015-09-21 22:46:44

只看TA 引用 举报 #23    得分 0

均陵鼠侠

Bbs5

Blank

引用 22 楼 learnc2015 的回复:

Quote: 引用 20 楼 zhao4zhong1 的回复:

别跟我说被编译器优化为立即数的取值不变的变量不是变量。

看来皇上错了?



你要跟老赵辩论问题,认真就输了。他会胡搅蛮缠,没完没了。

0 2015-09-22 09:48:37

只看TA 引用 举报 #24    得分 0

learnc2015

Bbs1

引用 24 楼 sholber 的回复:

Quote: 引用 22 楼 learnc2015 的回复:

Quote: 引用 20 楼 zhao4zhong1 的回复:

别跟我说被编译器优化为立即数的取值不变的变量不是变量。

看来皇上错了?


你要跟老赵辩论问题,认真就输了。他会胡搅蛮缠,没完没了。


回皇上,我对赵老师还是很葱白的,赵老师很热心,很愿意帮助别人,
心里是很感激赵老师的
不过皇上的功力也是非凡,也很热心,让我很感动,真皇恩浩荡啊

0 2015-09-22 10:00:37

只看TA 引用 举报 #25    得分 0

lm_whales

Bbs8

BlankBlank

int a =10;
可以编译为 mov  ebp[a],10
int a[]={10,9,8,7,6,5,4} :
就 很难 编译为这种代码
可能就成为 
a dd 10,9,8,7,6 ,5,4 了
也可能编译为
a_tmp dd  10,9,8,7,6 ,5,4  了//数据

然后 //代码
push esi
push edi
push  ecx
mov esi ,a_tmp
lea  edi,a[ebp]
rep movsd 

常量(表达式),编译成 立即数是很平常的,
变量,某种情况下也可能优化成常量,最终编译成立即数
串字面值
整型,浮点型,数组初始化列表,经常编译成 全局数据 用DB,DW,DD,DF,DQ,TB等伪指令定义
结构,类,可能编译为 结构类型
这一类初始化表,可能用结构定义方式定义
也可能用宏(宏指令)来定义
另外,由于编译器的各种策略,编译选项不同,可以用很多种不同的方法 ,编译同样的C,C++代码

0 2015-09-22 10:59:02

只看TA 引用 举报 #26    得分 0

learnc2015

Bbs1

引用 26 楼 lm_whales 的回复:

int a =10;
可以编译为 mov  ebp[a],10
int a[]={10,9,8,7,6,5,4} :
就 很难 编译为这种代码
可能就成为 
a dd 10,9,8,7,6 ,5,4 了
也可能编译为
a_tmp dd  10,9,8,7,6 ,5,4  了//数据

然后 //代码
push esi
push edi
push  ecx
mov esi ,a_tmp
lea  edi,a[ebp]
rep movsd 

常量(表达式),编译成 立即数是很平常的,
变量,某种情况下也可能优化成常量,最终编译成立即数
串字面值
整型,浮点型,数组初始化列表,经常编译成 全局数据 用DB,DW,DD,DF,DQ,TB等伪指令定义
结构,类,可能编译为 结构类型
这一类初始化表,可能用结构定义方式定义
也可能用宏(宏指令)来定义
另外,由于编译器的各种策略,编译选项不同,可以用很多种不同的方法 ,编译同样的C,C++代码


皇上,我是这么理解,初始化必须在内存里赋值才算是初始化
编译的时候赋值不算真正的初始化
我这样理解是否正确?

0 2015-09-22 11:20:25

只看TA 引用 举报 #27    得分 0

lm_whales

Bbs8

BlankBlank

引用 26 楼 lm_whales 的回复:

int a =10;
可以编译为
 push eax 
mov eax,10
 mov  ebp[a],eax //自动变量 ,全局的话 一般是 mov a,eax
.。。。。。
pop  eax


int a[]={10,9,8,7,6,5,4} :
就 很难 编译为这种代码
可能就成为  (全局数组 )
a dd 10,9,8,7,6 ,5,4 了
也可能编译为(自动数组)
a_tmp dd  10,9,8,7,6 ,5,4  了//数据

然后 //代码
push esi
push edi
push  ecx
mov esi ,a_tmp
lea  edi,a[ebp]
rep movsd 
。。。。

pop ecx
pop edi
pop esi
常量(表达式),编译成 立即数是很平常的,
变量,某种情况下也可能优化成常量,最终编译成立即数
串字面值
整型,浮点型,数组初始化列表,经常编译成 全局数据 用DB,DW,DD,DF,DQ,TB等伪指令定义
结构,类,可能编译为 结构类型
这一类初始化表,可能用结构定义方式定义
也可能用宏(宏指令)来定义
另外,由于编译器的各种策略,编译选项不同,可以用很多种不同的方法 ,编译同样的C,C++代码


修正一下

0 2015-09-22 11:20:33

只看TA 引用 举报 #28    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

盲人摸太阳
说是一物即不中

0 2015-09-22 11:39:20

只看TA 引用 举报 #29    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址;
人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

0 2015-09-22 11:41:38

只看TA 引用 举报 #30    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

闲来无事去读读gcc或g++源代码killtime吧。

0 2015-09-22 11:43:39

只看TA 引用 举报 #31    得分 0

均陵鼠侠

Bbs5

Blank

引用 31 楼 zhao4zhong1 的回复:

闲来无事去读读gcc或g++源代码killtime吧。



读killtimr?
赵老师的意思是他很渊博,视野开阔,看了不少源代码。但他忘了,正是他象老婆婆一样,总在劝大家不轻信、不盲从。信别人不信sholber,赵老师看来并不如他自诩的那样客观罢。

0 2015-09-22 12:41:52

只看TA 引用 举报 #32    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

http://fanyi.baidu.com/#en/zh/kill%20time

0 2015-09-22 13:46:14

只看TA 引用 举报 #33    得分 0

lm_whales

Bbs8

BlankBlank

所谓初始化,就是在数据定义的时候,同时给他一个值,
这个值,可以有这么几种方式给出

1)直接写到 可执行代码文件中,或者存储在磁盘某个(些)扇区中
     1.1) 烧写到 ROM 或者flash 等可执行非易失性存储器中。
     1.2)引导程序,加载操作系统的时候,把磁盘文件。或者扇区中的数据代码,加载到某块内存。
     1.3)操作系统加载程序的时候,直接根据文件中的数据在内存中准备好这些数据,然后启动应用程序开始执行。 
2)  运行时加载,或者初始化
    2.1) 某些数据可以直接嵌入指令作为立即数,也可以作为指令的其他部分,总之变成指令的一部分了,不是独立的数据了
    2.2)先存放在数据区,运行时加载(复制)初始化。  有单独的数据存在。
    2.3)调用函数初始化,这个是比较特殊的。不能优化掉的话,只能运行时加载,编译时不能确定初始化为什么值。
            包括用构造函数初始化,以及动态分配内存初始化指针。
    2.4)用变量初始化           
除了2.3)2.4)比较特殊外,所有的初始化方式,都可以在编译时候决定初始化成什么样子
所有这些初始化方式,编译器都可以确定下来
 
   

0 2015-09-22 14:45:11

只看TA 引用 举报 #34    得分 5

Joseph_1118

Bbs2

变量,其实是一块内存的名字罢了。
对于静态变量,确实是在运行前就已经确定了值。

0 2015-09-22 16:01:25

只看TA 引用 举报 #35    得分 0

line_us

Bbs2

问题很尖锐呀。

0 2015-09-22 16:03:51

只看TA 引用 举报 #36    得分 0

worldy

Bbs5

BlankBlankBlank

引用 14 楼 sholber 的回复:

Quote: 引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?


1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!



编译器写的,比如函数体中有
static n=100;
n=n++;

 编译器会将n放到程序读数据段的某个磁盘单元并且将其值设置为100,exe被加载的时候,整个数据段会原封不动的加载到内存,因此和n对应的存储单元就有100的起始值

0 2015-09-22 20:51:16

只看TA 引用 举报 #37    得分 0

worldy

Bbs5

BlankBlankBlank

引用 29 楼 zhao4zhong1 的回复:

盲人摸太阳
说是一物即不中



赵老师开始摸太阳了啊?

0 2015-09-22 20:54:32

只看TA 引用 举报 #38    得分 0

赵4老师

Bbs12

BlankBlankBlankBlank

https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&ch=33&tn=20041099_adr&wd=%E7%9B%B2%E4%BA%BA%E6%91%B8%E5%A4%AA%E9%98%B3&rsv_pq=d612627f0001fbce&rsv_t=661032m4J%2BvNnXjfCSwisWobdTCmfiGcy8%2BMIg3KUS8nekV6Ml%2BJrHIwPeUKKR4dONRj&rsv_enter=0&rsv_sug3=26&rsv_sug1=17&inputT=15477&rsv_sug4=15478

0 2015-09-22 22:00:50

只看TA 引用 举报 #39    得分 0

均陵鼠侠

Bbs5

Blank

引用 37 楼 worldy 的回复:

Quote: 引用 14 楼 sholber 的回复:

Quote: 引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?


1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!


编译器写的,比如函数体中有
static n=100;
n=n++;

 编译器会将n放到程序读数据段的某个磁盘单元并且将其值设置为100,exe被加载的时候,整个数据段会原封不动的加载到内存,因此和n对应的存储单元就有100的起始值



首先,你所说的,是业界流行的做法,但流行不代表就是确凿证据。人人都走阳关大道和捷径,但驴友就喜欢走没有路的偏僻丛林,你说不行?如果编译器只在EXE里为n保留一个位置,然后在程序开始执行的时候才用mov指针加一个立即数将100写到n对应的存储单元,难道不行?
其次,初始化这个词本身就没找到完整的定义,讨论起来自然各说各的。就像你说的,整个数据段加载到内存,这个覆盖内存原来东西的操作,不能叫初始化?
最后,n=n++不是一个有确定行为的表达式,赵老师会让你看置顶帖的。

0 2015-09-22 22:21:39

只看TA 引用 举报 #40    得分 5

均陵鼠侠

Bbs5

Blank

引用 38 楼 worldy 的回复:

Quote: 引用 29 楼 zhao4zhong1 的回复:

盲人摸太阳
说是一物即不中


赵老师开始摸太阳了啊?


太阳他辈子怕是摸不着了,朕建议他摸电烙铁,其实也挺烫的。

0 2015-09-22 22:24:18

只看TA 引用 举报 #41    得分 0

worldy

Bbs5

BlankBlankBlank

引用 40 楼 sholber 的回复:

Quote: 引用 37 楼 worldy 的回复:

Quote: 引用 14 楼 sholber 的回复:

Quote: 引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?


1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!


编译器写的,比如函数体中有
static n=100;
n=n++;

 编译器会将n放到程序读数据段的某个磁盘单元并且将其值设置为100,exe被加载的时候,整个数据段会原封不动的加载到内存,因此和n对应的存储单元就有100的起始值


首先,你所说的,是业界流行的做法,但流行不代表就是确凿证据。人人都走阳关大道和捷径,但驴友就喜欢走没有路的偏僻丛林,你说不行?如果编译器只在EXE里为n保留一个位置,然后在程序开始执行的时候才用mov指针加一个立即数将100写到n对应的存储单元,难道不行?
其次,初始化这个词本身就没找到完整的定义,讨论起来自然各说各的。就像你说的,整个数据段加载到内存,这个覆盖内存原来东西的操作,不能叫初始化?
最后,n=n++不是一个有确定行为的表达式,赵老师会让你看置顶帖的。



按照你的MOV方法进行初始化,那如果我初始化的是一个表呢?编译器创建一个循环还是一个数据生成一条初始化指令?
n=n++是我写错了,你也不用太在意

0 2015-09-23 08:32:02

只看TA 引用 举报 #42    得分 0

均陵鼠侠

Bbs5

Blank

引用 42 楼 worldy 的回复:

Quote: 引用 40 楼 sholber 的回复:

Quote: 引用 37 楼 worldy 的回复:

Quote: 引用 14 楼 sholber 的回复:

Quote: 引用 11 楼 zhao4zhong1 的回复:

编译的时候没初始化,那代码段汇编指令中的常量是谁写上去的?


1,汇编指令中还有常量,这个没听说过;
2,初始化是什么意思,赵老师学C数十载,竟然到现在还没弄明白。
赵老湿以为朕是外国人,不懂中国话吗!


编译器写的,比如函数体中有
static n=100;
n=n++;

 编译器会将n放到程序读数据段的某个磁盘单元并且将其值设置为100,exe被加载的时候,整个数据段会原封不动的加载到内存,因此和n对应的存储单元就有100的起始值


首先,你所说的,是业界流行的做法,但流行不代表就是确凿证据。人人都走阳关大道和捷径,但驴友就喜欢走没有路的偏僻丛林,你说不行?如果编译器只在EXE里为n保留一个位置,然后在程序开始执行的时候才用mov指针加一个立即数将100写到n对应的存储单元,难道不行?
其次,初始化这个词本身就没找到完整的定义,讨论起来自然各说各的。就像你说的,整个数据段加载到内存,这个覆盖内存原来东西的操作,不能叫初始化?
最后,n=n++不是一个有确定行为的表达式,赵老师会让你看置顶帖的。


按照你的MOV方法进行初始化,那如果我初始化的是一个表呢?编译器创建一个循环还是一个数据生成一条初始化指令?
n=n++是我写错了,你也不用太在意



干嘛钻牛角尖,我的意思很简单,不要拿C实现的细节,什么段啊、堆啊栈啊说事,解决这个问题不需要这些东西,解决C的问题也不需要钻到这个层次。
好吧,如果是初始化一个表,这个表及其元素都只具有自动存储期,那么,我宁愿使用MOV指令的序列。

0 2015-09-23 09:29:37

只看TA 引用 举报 #43    得分 0

kingtown11

Bbs1

静态和全局变量的初始化操作确实是编译后保存在文件中的。
具体实验方法可以用二进制修改器,修改EXE中静态变量的值,然后直接启动EXE看是原来未修改的值,还是修改后的值。

程序加载后,会在main函数之前将各种数据初始化,其中也包括着全局和静态。

PE里面也可以看出来,前面有人讲过了,不阐述了。。

汇编前面看大家讨论了这么多,就不参合了,其实全局变量赋值的形式就是一个偏移地址的值,反汇编看的话其实唯一的区别是main函数前还是main函数后给的,进入main函数前就赋值到内存里了的话,就是说明程序在加载入内存的时候,全局变量已经有值了。
不过这个不具代表性,因为如果是自定义程序入口函数,自己裁剪一下一切皆有可能。

0 2015-09-23 14:34:20

只看TA 引用 举报 #44    得分 0

yao_zhuang

Bbs3

引用 5 楼 zhao4zhong1 的回复:

有的变量是在编译的时候初始化的,有的变量是在运行的时候初始化的。


通常编译时能够进行的计算编译时就完成了, 如常量计算一类的

0 2015-09-27 16:56:32

只看TA 引用 举报 #45    得分 0

贾可

Bbs5

代码:

C/C++ code?

1

2

3

4

5

6

int f (void)

{

    static int mm=1;

    mm++;

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

}

可以理解为:

C/C++ code?

1

2

3

4

5

6

int mm=1;

int f (void)

{

    mm++;

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

}

且 mm 仅在函数 f 内可见

0 2015-09-28 10:20:01

只看TA 引用 举报 #46    得分 5

man122

Bbs1

不是应该打印2,3 吗?为啥是1, 2~!

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值