C内存布局相关问题
问题描述
如下代码输出什么:
#include<stdio.h>
int main()
{
char a=0;
char b=0;
int *p=(int *)&b;
*p=258;
printf("%d %d",a,b);
return 0;
}
在看国外一本linux方面的书,里面讲到c语言内存布局相关,书中说这个程序运行结果是1 2,可是我再我的电脑(mac)上运行时02,并且想不明白这是为什么.
我目前仅有的思路如下:
258的二进制形式100000010
指针p指向了字符b的起始地址,字符与整形的地址对比可以通过下面的代码得出:
#include <stdio.h>
int main()
{
char a = 0;
char b = 0;
char c = 0;
int d = 0;
int e = 0;
int f = 0;
printf("%p\n",&a);
printf("%p\n",&b);
printf("%p\n",&c);
printf("%p\n",&d);
printf("%p\n",&e);
printf("%p\n",&f);
return 0;
}
代码输出
0x7fffc38df0df
0x7fffc38df0de
0x7fffc38df0dd
0x7fffc38df0d8
0x7fffc38df0d4
0x7fffc38df0d0
地址由高到低,所以我的理解是*p复制258(258的二进制形式100000010)会去覆盖字符a b 原有的值,所以b的值是00000010 a的值是000000001,a的值是1,b的值是2.此时涉及到大端与小端方式,我通过如下程序判断出我电脑环境为大端方式:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int hoge = 0x12345678;
unsigned char *hoge_p =(unsigned char *)&hoge;
printf("%x\n",hoge_p[0]);
printf("%x\n",hoge_p[1]);
printf("%x\n",hoge_p[2]);
printf("%x\n",hoge_p[3]);
return 0;
}
可是我实际运行中确实0 2.
估计你开了编译器优化。
我的环境:
Ubuntu 16.04 (64 bit)
gcc 5.4.0
不开优化直接编译,结果的确是 1 2
;但一旦开了优化(-O1
, -O2
, -O3
, -Og
结果都一样,其中 -Og
会报错),结果就变成了 0 2
。原因在于:编译器在编译阶段就已经将值算好了,你输出的其实是常量。
拿 -O1
优化的汇编代码举例(使用 gcc test.c -O1 -S
获得,这里只贴核心部分):
movl $2, %ecx
movl $0, %edx
movl $.LC0, %esi
movl $1, %edi
movl $0, %eax
call __printf_chk
movl $0, %eax
%edi
, %esi
, %edx
, %ecx
分别是 __printf_chk
的参数,%esi
指向 %s %s
的地址。
可以发现最后两个参数并没有访问栈区,而是直接使用了立即数 0 和 2,可见这两个值的计算在编译期就已经完成了。
这篇关于C内存布局相关问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!