为验证C++中的编译器内存分配方式而引出的问题

crazyhzc 2011-08-09 12:11:18
我为了想弄清楚在Qt中为变量分配内存的方式,于是写了下面的简单的程序,创建的项目是Qt4控制台应用程序,Windows下。

#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
int i;
int a[5];
int j=0;
for(i=0; i <= 4; i++)
a[i] = 0;
i = 10;
j = 11;

printf(" i 地址:%d,值:%d\n",&i,i);
printf("a[4]地址:%d,值:%d\n",a+4,*(a+4));
printf("a[3]地址:%d,值:%d\n",a+3,*(a+3));
printf("a[2]地址:%d,值:%d\n",a+2,*(a+2));
printf("a[1]地址:%d,值:%d\n",a+1,*(a+1));
printf("a[0]地址:%d,值:%d\n",a,*(a));
printf(" j 地址:%d,值:%d\n\n",&j,j);

printf(" 地址:%d,值:%d\n",a+5,*(a+5));
printf(" 地址:%d,值:%d\n",a-1,*(a-1));

return app.exec();
}
运行的结果是
i 地址:2293540,值:10
a[4]地址:2293536,值:0
a[3]地址:2293532,值:0
a[2]地址:2293528,值:0
a[1]地址:2293524,值:0
a[0]地址:2293520,值:0
j 地址:2293516,值:11

地址:2293540,值:10
地址:2293516,值:11


这里完全没有什么问题,说明Qt中的编译器是按照内存地址递减的方式来给变量分配内存的,接着我写了下面一段代码
#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
int i;
int a[5];
int j=0;
for(i=0; i <= 4; i++)
a[i] = 0;
i = 10;
j = 11;

printf(" 地址:%d,值:%d\n",a+5,*(a+5));
printf(" 地址:%d,值:%d\n",a-1,*(a-1));

return app.exec();
}
运行的结果却是
地址:2293536,值:1781959496
地址:2293512,值:0
比较这两个程序,为什么会两个不同的输出结果,第一个程序中多出的几个输出语句对后面的输出语句有什么影响吗?

我还写了一段代码
#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
int i;
int a[5];
int j=0;
for(i=0; i <= 5; i++)
*(a+i) = 0;
i = 10;
j = 11;

printf(" 地址:%d,值:%d\n",a+5,*(a+5));
printf(" 地址:%d,值:%d\n",a-1,*(a-1));

return app.exec();
}
第一个程序已经证实了Qt的编译器是按照内存地址递减的方式给变量分配内存的,如果是这样,把循环次数增加一次后,当循环到i=5时,(a+i)指向的应该是存放变量i的内存单元,此时对*(a+i)赋值为0,即i的值变为0,然后会一直循环下去,但是执行的时候为什么没出现死循环的现象,而是把后面的两个输出语句执行后崩溃了,难道是编译器有越界检查,然后做出了相应的处理。各位大侠指点下,小弟不胜感激!
...全文
139 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
局部变量的地址是不能确定的。
编译器爱咋安排就咋安排。
a[0] .. a[4]必然是连续的。其他就不能确定了。
stjay 2011-08-09
  • 打赏
  • 举报
回复
i,j有可能被优化掉
查看反汇编对照一下
帅得不敢出门 2011-08-09
  • 打赏
  • 举报
回复
比较这两个程序,为什么会两个不同的输出结果.
两次运行, 结果不同是由于系统运行环境就存在差异, 栈从高到低都是一样的.

每三个不会死循环是很自然的.
*(a+i) = 0; //i=0后,就会执行下一句i=10; 而不会跳到前面执行.
i = 10;
j = 11;
crazyhzc 2011-08-09
  • 打赏
  • 举报
回复
由于第一个程序我以为编译器给变量分配内存是按照定义变量的顺序来的,但是后面几个程序又不是这样的,所以就很疑惑。&i和&j对分配内存的顺序确实有影响,我单步调试的时候看了一下汇编代码,还是不懂&i和&j对编译器分配内存的顺序为什么有影响,这应该跟编译器内部的编译机制有关,谢谢大家的解答!
crazyhzc 2011-08-09
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 stjay 的回复:]

引用 5 楼 crazyhzc 的回复:

我又写了一段代码
#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

int i;
int a[5];
int j;

*(&a……
[/Quote]
i = 10;j=11和*(&i)=10;*(&j)=11这两种赋值有什么区别吗
stjay 2011-08-09
  • 打赏
  • 举报
回复
for循环不用说啦,会用寄存器优化的
stjay 2011-08-09
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 crazyhzc 的回复:]

我又写了一段代码
#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

int i;
int a[5];
int j;

*(&a……
[/Quote]

我还是说,i,j如果只是简单的赋值,编译时会被优化掉了
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 crazyhzc 的回复:]

1楼没懂我的意思,前面两个程序的比较,我并不是说两个的地址值不同,而是(a+5)所指向的应该是存放变量i的内存,而(a-1)所指向的是存放变量j的内存,那么*(a+5)和*(a-1)中的值应该分别是i和j的值,第一个程序中是这样的,但是第二个程序中却不是这样。
第三个程序i=10,j=11在循环之外,在i=5的时候进入循环是i的值应该又重新赋为0了。
[/Quote]
局部变量 全局变量 ,在内存中的顺序是未知的 。不是先声明就得在前面,后声明就得在后面。
至善者善之敌 2011-08-09
  • 打赏
  • 举报
回复
单步调试一下,看内存窗口
赵4老师 2011-08-09
  • 打赏
  • 举报
回复
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
crazyhzc 2011-08-09
  • 打赏
  • 举报
回复
我又写了一段代码
#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

int i;
int a[5];
int j;

*(&j) = 0;
*(&i) = 0;

for(i=0; i <= 5; i++)
*(a+i) = 0;
i = 10;
j = 11;

return app.exec();
}
这段程序执行时就会陷入死循环,可见是&i和&j对编译器给变量分配内存时有影响,但是不懂为什么会这样。
crazyhzc 2011-08-09
  • 打赏
  • 举报
回复
1楼没懂我的意思,前面两个程序的比较,我并不是说两个的地址值不同,而是(a+5)所指向的应该是存放变量i的内存,而(a-1)所指向的是存放变量j的内存,那么*(a+5)和*(a-1)中的值应该分别是i和j的值,第一个程序中是这样的,但是第二个程序中却不是这样。
第三个程序i=10,j=11在循环之外,在i=5的时候进入循环是i的值应该又重新赋为0了。

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧