user-0 提问: C语言中变量何时分配空间？

回复:
user: user-1
content: 引用 24 楼 funnywhere 的回复:[quote=引用 23 楼 lin5161678的回复:][quote=引用 22 楼 funnywhere的回复:][quote=引用 21 楼 lin5161678的回复:][quote=引用 20 楼 funnywhere 的回复:] 并没有优化掉，都在的。 那么你的依据呢 你凭什么说 b变量还在呢[/quote] 因为我找到正确答案了[/quote] 别扯 这只是黑盒测试 没什么能叫做答案[/quote] 那就不叫答案吧，因为我看到一篇介绍gcc如何进行内存分配的文章，可以说找到正确的解释了。[/quote] 局部变量分配汇编指令 Intel 是 sub esp，xxx，ARM处理器是 sub     sp, sp, #xxx ，不管什么编译器，就这种方法，还正确答案，别逗

user: user-1
content: 引用 28 楼 火花20180731 的回复:可执行文件相当于一个内存模板，系统会按照这个内存模板起一个进程，按模板中的内容为进程分配内存(给一个空闲的虚拟的地址区间，可与物理内存建立映射)，并填充初始数据。第一次进程运行结束后，占用的内存被释放，用过的地址区间再次空闲。第二次进程运行再次从这个空闲地址开始分配，所以两次地址打印相同。现代操作系统都是虚拟内存，进程间内存是互不相干的，跟第几次运行都没关系，即时同时运行也一样

user: user-1
content: 引用 29 楼 funnywhere 的回复:[quote=引用 26 楼 赵4老师的回复:]理解和讨论之前请先学会如何观察！  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！ 确实很有道理。[/quote] 老赵的话，十年前就是复制粘贴的，水了一辈子了。

user: user-2
content: 如果你的代码中没有使用某个变量，通常会被编译器优化掉（取决于编译器优化级别），如果你只读使用，编译器会将其优化为常量嵌入到代码中（立即数），只有你对它进行了写操作或者取地址，编译器才会为它实际分配空间

user: user-0
content: 引用 23 楼 lin5161678的回复:[quote=引用 22 楼 funnywhere的回复:][quote=引用 21 楼 lin5161678的回复:][quote=引用 20 楼 funnywhere 的回复:] 并没有优化掉，都在的。 那么你的依据呢 你凭什么说 b变量还在呢[/quote] 因为我找到正确答案了[/quote] 别扯 这只是黑盒测试 没什么能叫做答案[/quote] 那就不叫答案吧，因为我看到一篇介绍gcc如何进行内存分配的文章，可以说找到正确的解释了。

user: user-0
content: 引用 26 楼 赵4老师的回复:理解和讨论之前请先学会如何观察！  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！ 确实很有道理。

user: user-3
content: 可执行文件相当于一个内存模板，系统会按照这个内存模板起一个进程，按模板中的内容为进程分配内存(给一个空闲的虚拟的地址区间，可与物理内存建立映射)，并填充初始数据。第一次进程运行结束后，占用的内存被释放，用过的地址区间再次空闲。第二次进程运行再次从这个空闲地址开始分配，所以两次地址打印相同。

user: user-2
content: 以前的老赵又回来了～～～

user: user-4
content: 理解和讨论之前请先学会如何观察！  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

user: user-5
content: 引用 22 楼 funnywhere的回复:[quote=引用 21 楼 lin5161678的回复:][quote=引用 20 楼 funnywhere 的回复:] 并没有优化掉，都在的。 那么你的依据呢 你凭什么说 b变量还在呢[/quote] 因为我找到正确答案了[/quote] 别扯 这只是黑盒测试 没什么能叫做答案

user: user-6
content: 只單獨輸出a或b，是不是意味著這時候另一個變量在整個程序生命期中沒有用到？比如：  #include <stdio.h> #include <stdlib.h> int main() {     int b ;     int a ;     printf("%x\n",&a);  //只输出a的地址，本人机器上为61FE1C     system("pause");     return 0; }  這段程序中，b只在定義時出現一次。  這就是你要明白的其中一點：編譯器有優化功能，它掃描了整個程序發現b其實可以不要，於是就很可能被省略掉了。 那麽這個時候，不管你輸出的是a還是b，它的地址分配都是一樣的，即屬於該程序的變量空間只有一個整數。

user: user-0
content: 引用 21 楼 lin5161678的回复:[quote=引用 20 楼 funnywhere 的回复:] 并没有优化掉，都在的。 那么你的依据呢 你凭什么说 b变量还在呢[/quote] 因为我找到正确答案了

user: user-5
content: 引用 20 楼 funnywhere 的回复:并没有优化掉，都在的。 那么你的依据呢 你凭什么说 b变量还在呢

user: user-0
content: 引用 19 楼 老马何以识途的回复:只單獨輸出a或b，是不是意味著這時候另一個變量在整個程序生命期中沒有用到？比如：  #include <stdio.h> #include <stdlib.h> int main() {     int b ;     int a ;     printf("%x\n",&a);  //只输出a的地址，本人机器上为61FE1C     system("pause");     return 0; }  這段程序中，b只在定義時出現一次。  這就是你要明白的其中一點：編譯器有優化功能，它掃描了整個程序發現b其實可以不要，於是就很可能被省略掉了。 那麽這個時候，不管你輸出的是a還是b，它的地址分配都是一樣的，即屬於該程序的變量空間只有一個整數。 并没有优化掉，都在的。

user: user-0
content: 引用 13 楼 眼里有光～的回复:函数内部的变量是局部变量，比如你int a,b，这种非静态局部变量是放在栈上的，栈区是操作系统来管理的，程序在运行的时候操作系统自动为局部变量分配空间，局部变量出了作用域以后，操作系统自动回收这部分空间，也就是说不需要由程序员自己去申请和释放这块内存。  你上面出现的情况，每次运行单输出a和b的地址有时是一样的，这是正常情况，程序本次运行操作系统可能将这个地址分配给a，下次运行操作系统将这个地址分配给b，操作系统怎么分配栈区地址其实根本不用程序员操心。   感觉跟操作系统关系不大。感觉是gcc编译器的某种策略，换成msvc就没有这个现象。

user: user-7
content: 函数内部的变量是局部变量，比如你int a,b，这种非静态局部变量是放在栈上的，栈区是操作系统来管理的，程序在运行的时候操作系统自动为局部变量分配空间，局部变量出了作用域以后，操作系统自动回收这部分空间，也就是说不需要由程序员自己去申请和释放这块内存。  你上面出现的情况，每次运行单输出a和b的地址有时是一样的，这是正常情况，程序本次运行操作系统可能将这个地址分配给a，下次运行操作系统将这个地址分配给b，操作系统怎么分配栈区地址其实根本不用程序员操心。

user: user-8
content: 短时间内一样的地址巧合而已。

user: user-0
content: 引用 7 楼 qybao 的回复:[quote=引用 6 楼 funnywhere 的回复:] 你再给a也赋个值10000，你会发现如果只单独输出a或b的地址，也是一样的。 你把你的代码和运行结果贴出来看看 #include <stdio.h> #include <stdlib.h> int main() {     int b = 10000;     int a = 10000;     printf("%X\n",&b);   //你确定轮流注释这两句打印语句运行出来的结果一样？a，b同时被使用，编译优化不会舍弃任何一个，内存地址肯定不同     //printf("%X\n",&a);  //估计你代码哪里有问题，要不就是进程加载时不是重复使用原来的内存（这很正常）     system("pause");     return 0; }[/quote]

user: user-0
content: 轮流注释地址就是一样的啊。试了好多种方案都不知道怎么解释。要不我就不会发帖问了。

user: user-9
content: 程序加载到内存时才会分配内存，但是编译器会指定偏移量。比如数组会指定长度～