c中定义变量的内存分配顺序问题(极易错!!!)

来源:互联网 发布:史丹利快报的淘宝店 编辑:程序博客网 时间:2024/04/20 10:36

对于c语言中大家都知道所有的变量都必须是先定义后使用的,但是但是,对于好多人而言,基本上没有人(不管是老手还是菜鸟)来注意自己的编译器和操作系统对这个东西是如何处理的,


1,如果全是一样的类型,比如全是int(char,double,float),编译器会如何分配呢??是从大到小还是从小到大,,

2, 数组的分配方式和基本类型一样吗??编译器又是如何处理的??

3, 如果是基本类型和数组混合呢??

4,倘使是不同的操作系统呢,??它又有什么不同呢??


好了,接下来,我们大家一起看一看吧!!



(注意:下面我们的程序都是在:dev-C++ 5.11,  win7,32位的系统下运行的结果)

1.全是一样的类型

#include<stdio.h>#include<conio.h>int main(){int a;int b;int c;printf("a is ip:%p\n", &a);printf("b is ip:%p\n", &b);printf("c is ip:%p\n", &c);printf("nihao, mingtian");getch();return 0;}

好,接下来我们看一看结果!


由图可知,我们的编译器和系统给它们分配的时候是,先找了一块空闲区,确定了之后,然后将高地址给了第一个定义的变量,将次高地址给了第二个变量,其他依次类推,可以得出,我们的地址分配是从高到底的!!




下面这个是全是char类型时候的分配情况,所以说我们上面的总结是正确的!

当然我相信,就是全部换成float,double也是一样得


2, 数组的话

#include<stdio.h>#include<conio.h>int main(){char a[3];printf("a[0]'s is ip:%p\n", &a);printf("a[0] is ip:%p\n", &a[0]);printf("a[1] is ip:%p\n", &a[1]);printf("a[2] is ip:%p\n", &a[2]);printf("a[3] is ip:%p\n", &a[3]);printf("nihao, mingtian");getch();return 0;}

可以看到结果:


大家可以很清楚的看到,我们的编译器和操作系统对其的分配方式

还是同样的道理,先找空闲区,然后将数组里的第一个元素分到了底地址处,将第二个分配到了次底地址处,后面的同理,所以我们可以总结一下:对于数组,分配方式是从低到高,跟基本类型的分配方式不一样,


此时,我们大家再来看一个例子:

#include<stdio.h>#include<conio.h>int main(){char a[3];char b[2];printf("a[0]'s is ip:%p\n", &a);printf("a[0] is ip:%p\n", &a[0]);printf("a[1] is ip:%p\n", &a[1]);printf("a[2] is ip:%p\n", &a[2]);printf("a[3] is ip:%p\n\n\n", &a[3]);printf("b[0] is ip:%p\n", &b[0]);printf("b[1] is ip:%p\n", &b[1]);printf("b[2] is ip:%p\n", &b[2]);printf("nihao, mingtian");getch();return 0;}


大家看结果:


请大家务必牢记:这里经常被好多人不重视:

现在我们也能清晰的看到:对于两个数组,我们可以将其看作两个基本类型,他们的内存分配遵从从高到低,所以我们可以看到a[0]的地址比b[0]高,

然后他们具体的位置取决于自己数组的大小,也就是说对于先定义a数组,然后再定义b数组的情况,现将整个a数组放在了高地址,将整个b数组放在了相对的次高地址

然后,具体对数组内部的东西进行分配处理,内部其实也就是我们上面说的分配从低到高

大家可能会很有疑惑为什么a[0],b[2]的地址是一样的??

大家不妨自己想一想,其实也很简单:

先定义a数组,整体放在了高地址处,而对于数组内部a[0]放在了相应的底地址处(0022febd)

而对于数组b,整体放在了底地址处,同理数组内部b[2]也就放在了相对于b[0](0022febb)处的高位,也就是(0022febd)

但是,但是,但是,大家一定要清楚,此时我们的是C,所以我们的编译器此时是对b[2]是不分配的内存的,如果我们非要取出东西或探究地址,那也只能在b[1]地址(0022febc)的相对下一个,也就是a[0]的地址了



哈哈,很简单吧!!




3:混合(基本类型和数组)


#include<stdio.h>#include<conio.h>int main(){int a;char b[2];int c;printf("a is ip :%p \n", &a);printf("b[0] is ip:%p\n", &b[0]);printf("b[1] is ip:%p\n", &b[1]);printf("b[2] is ip:%p\n", &b[2]);printf("c is ip :%p\n", &c);printf("nihao, mingtian");getch();return 0;}

运行结果如下:



同样的:我们分析还是将数组当做基本类型对待

所以a变量在内存地址最高位,b数组在内存地址次高位,c其次,

当a确定了位置(0022febc)后,也就确定了b[0](0022feba),因为数组是从低到高,b[1]是(0022febb),b[2]是(0022febc)(注意b[2]应该不存在,也就是没有为其分配内存,所以也就是b[1]的位置相对下一个,也就是a的地址处),同理也就确定了C的地址(0022feb4)

至于为什么是b4,而不是b9,大家如果有兴趣的话可以看看我的另外一篇博客

关于内存结构体共用体在linux/window下的分配情况:

点击打开链接:http://blog.csdn.net/msdnwolaile/article/details/50158463



好好,接下来我们来看看linux下是如何做的:


我们也可以很清楚的看到,里面的三个变量的类型是一样的,都是int

结果如下:

同样的,大家可以看到,变量a先定义,但是a的地址还低(0x7ffc4fb9c134)

然后定义变量b,b的地址比a要高一点(0x7ffc4fb9c138

然后依次c,地址为(0x7ffc4fb9c13c

所以,我们可以同样总结,在linux(我的是ubuntu kylin 14.04)下,一般来说,对于基本变量的分配是从低地址到高地址的



当然不管是window还是linux下,

定义  :   int   a, b, c;

int  a;

int  b;

int  c;

上面两个都是一样的!!!!分配方式是并不影响的



2, linux下的数组



可以看到上面是对数组的检验:

结果如下:


好啦,我们可以分析结果,首先根据a[0],a[1],a[2]的地址的大小,知道对于数组也是如window,是从低到高的

而如果我们将两个数组都当做基本类型

大家注意,这里可就跟上面不一样了,从高到低的,



哈哈,这回大家明白了吧!!


0 0
原创粉丝点击