#include <stdio.h>
int main() {
char buf[4] = {(char)0xCC,(char)0xCC,(char)0xCC,(char)0xCC};
int cccc = 0xCCCCCCCC;
printf( "1.0x%08llx\n", reinterpret_cast<unsigned long long>(((void**)buf)[0]));
printf( "2.0x%08llx\n", reinterpret_cast<unsigned long long>((void*)0xCCCCCCCC));
printf( "3.0x%08llx\n", static_cast<unsigned long long>(0xCCCCCCCC));
printf( "4.0x%08llx\n", static_cast<unsigned long long>(-1));
printf( "5.0x%08llx\n", reinterpret_cast<unsigned long long>((void*)-1));
printf( "6.0x%08llx\n", static_cast<unsigned long long>(cccc));
printf( "7.0x%08llx\n", reinterpret_cast<unsigned long long>((void*)cccc));
printf( "8.0x%08llx\n", reinterpret_cast<unsigned long long>(((void**)&cccc)[0]) );
return 0;
}
估计没几个人能说出正确的结果....
其实这段代码根本没有正确的结果.因为标准里没有规定具体的实现.不同的编译器编译出来的结果也是五花八门.
虽然转型是不被提倡的.但有的时候确实无法避免.所以很有必要了解具体的编译行为.
对于指针和整数之间的转型,标准里只明确必须达到 指针转整数再转指针 或 整数转指针再转整数,结果不变.这种效果.(有个前提,就是尽量保证和物理机器的地址的一致性.不要造成混淆)
于是,对于指针和整型的转换就有了几种不同的做法:
1.按unsigned转换.
2.按signed转换.
3.按目标类型转换.
对于不用做提升操作的转换,这些方式都差不多.做对于要做类型提升操作的转换.就有可能出岔子了.
VC的编译结果如下:
1.0xffffffffcccccccc
2.0xcccccccc
3.0xcccccccc
4.0xffffffffffffffff
5.0xffffffff
6.0xffffffffcccccccc
7.0xffffffffcccccccc
8.0xffffffffcccccccc
可以看到,正常情况下,VC对指针的提升是按signed类型操作的.但请注意第2项.当把一个无符号常量强制转为指针再进行提升的时候,就变成按unsigned类型操作了...相同结果的还有第5项.这里VC竟然区别对待常量和变量...
同样的代码,gcc的结果是:
1.0xffffffffcccccccc
2.0xffffffffcccccccc
3.0xcccccccc
4.0xffffffffffffffff
5.0xffffffffffffffff
6.0xffffffffcccccccc
7.0xffffffffcccccccc
8.0xffffffffcccccccc
GCC的结果就具有很好的一致性.只要是指针都是按signed类型进行提升.
而icl则相反:
1.0xcccccccc
2.0xcccccccc
3.0xcccccccc
4.0xffffffffffffffff
5.0xffffffff
6.0xffffffffcccccccc
7.0xcccccccc
8.0xcccccccc
只要是指针都是按unsigned类型进行提升
其它我还测试了bcc,dmc,owcc,mwcc.
其中dmc和icl的结果一致.
bcc和owcc的结果一致,都是和VC有点类似的方式.
mwcc则是按自己的方式进行操作.
总的来说,gcc,icl,dmc的转型都具有很好的一致性.虽然他们结果不同,但不会像vc那样还区别对待常量.
虽然这个东西不是标准的内容,但因为转型没法完全避免.了解清楚总比错的莫名其妙好...
和大家共勉了...