编译器的一些疑惑

对32位机器来说,不同类型的指针从本质上说都是一个32位的地址,只不过指向的地址大小是不同的。如:

char *a     a指向的地址为一个字节大小;

int *b        b指向的地址为四个字节的大小。

于是我想看看,不同类型指针间的区别,于是有了下面的程序:

#include <stdio.h>
int main()
{
char a=6;
int *b;
b=(int*)&a;
printf("%x\n",*b);

    return 0;
}


理论上&a是char*的指针,而b是int*型的,那么*b的值应该就是从a的地址开始向上读四个字节的数据,即*b的第一个字节是a的值6,第二三四个字节的数据是不确定的,可运行后发现,*b=22ff4b06,经实验发现22ff4b是a的地址,进一步验证后发现,22ff4c存储内容是4b,22ff4d存储内容是ff,22ff4e存储内容是22,22ff4f存储内容是00;即存储变量a地址的前四个字节的内容存储的a地址的值,当然a的类型变化结果也是这样,于是*b从a的地址处开始读值,第一个字节为6,第二个字节为46,第三个字节为ff,第四个字节为22,故*b为22ff4b06,通过上面的实验可以看出编译器默认的变量后面四个字节的地址所指向的内容是变量的地址,于是为了验证不同类型指针间的区别,更合理的程序应该是这样的:

#include <stdio.h>


int main()
{
char a = 1;
char b = 2;
char c = 3;
char d = 4;

int* p = (int*)&d;

printf("a=%x\n",&a);
printf("b=%x\n", &b);
printf("c=%x\n", &c);
printf("d=%x\n",&d);

printf("*p=%x\n",*p);

    return 0;
}


堆栈是向下增长的,那么按上面的分析,*p从d的地址开始向上读四个字节的地址,因此结果应该为1020304,运行结果正常,可是如果我把printf("a=%x\n",&a);printf("b=%x\n", &b);printf("c=%x\n", &c);中的任意一句删掉,结果就不正常了,为什么呢?原来现代的编译器都会对程序做一个优化,程序中没有用到的变量,在编译的时候会被删除,所以......
我用的编译器是gcc,没有在别的编译器上面试,当然对全局变量也是int i; int i;默认会删除一个变量,由此在程序中应尽量按便准的C规则来,不能过分依赖编译器!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值