诡异的转型陷阱.......

redleaves 2010-06-07 11:50:49
#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那样还区别对待常量.

虽然这个东西不是标准的内容,但因为转型没法完全避免.了解清楚总比错的莫名其妙好...
和大家共勉了...
...全文
251 24 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2010-06-17
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 cs_yagami 的回复:]
引用 14 楼 zhao4zhong1 的回复:

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!

怎麼覺得這幾句話出現了好幾次..囧[/Quote]
敢問有幾個人照做了?
赵4老师 2010-06-16
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 milkylove 的回复:]
引用 16 楼 cs_yagami 的回复:

引用 14 楼 zhao4zhong1 的回复:

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东……
[/Quote]
另外再悄悄的告诉你 看汇编代码是无法区分signed 和 unsigned的。

那请问milkylove:汇编指令JA和JG的区别?
失落的凡凡 2010-06-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 cs_yagami 的回复:]

引用 14 楼 zhao4zhong1 的回复:

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!

怎麼覺得這幾句話出現了好幾次..囧
[/Quote]

悄悄的告诉你 这是位机器人大叔, 只会说三句话

另外再悄悄的告诉你 看汇编代码是无法区分signed 和 unsigned的。
annhoo 2010-06-09
  • 打赏
  • 举报
回复
谢谢,分享。真是难为你了!呵呵
scudc 2010-06-08
  • 打赏
  • 举报
回复
我的vc6还要编译错误。。。。
ForestDB 2010-06-08
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 zhao4zhong1 的回复:]
不要迷信书、考题、老师;
要迷信CPU、编译器、调试器。
[/Quote]
这个可以顶。
支持LZ。
shuai13869896140 2010-06-08
  • 打赏
  • 举报
回复
LZ牛人,真是有心了```
yunyun1886358 2010-06-08
  • 打赏
  • 举报
回复
不懂,unsigned long long。
顺便问一下,两个long是什么意思?
z569362161 2010-06-08
  • 打赏
  • 举报
回复
中科院IT工程硕士 为IT人加油
cs_yagami 2010-06-08
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zhao4zhong1 的回复:]

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
[/Quote]
怎麼覺得這幾句話出現了好幾次..囧
赵4老师 2010-06-08
  • 打赏
  • 举报
回复
不要迷信书、考题、老师;
要迷信CPU、编译器、调试器。
赵4老师 2010-06-08
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
azure110 2010-06-08
  • 打赏
  • 举报
回复
支持 lz
pengzhixi 2010-06-08
  • 打赏
  • 举报
回复
收藏下
  • 打赏
  • 举报
回复
Take It Easy
cattycat 2010-06-08
  • 打赏
  • 举报
回复
谢谢分享。
selooloo 2010-06-08
  • 打赏
  • 举报
回复
用dev printf %llx 仍然按32位打印的
z569362161 2010-06-08
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yunyun1886358 的回复:]
不懂,unsigned long long。
顺便问一下,两个long是什么意思?
[/Quote]

新语法,超长整型。但是需要编译器支持
hzy694358 2010-06-08
  • 打赏
  • 举报
回复
牛逼哄哄……
学习
saiweng198 2010-06-08
  • 打赏
  • 举报
回复
学习了,DING……
加载更多回复(4)

65,184

社区成员

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

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