请大家帮忙看下这段代码

_skytrails 2014-05-18 06:54:15
在书上看了段代码,发现书上的结果与我算的不一样,看了答案后我发现他的解释好像有道理。后来我用gcc编译这段代码,发现得出的结果与我的一样。求解释。代码如下:
unsigned char a = 0xA5;
unsigned char b = ~a >> 4 + 1;
printf("b=%d\n",b);

求他的输出结果:
先把题目贴出,后面我再贴出结果。
...全文
311 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
unituniverse2 2014-05-21
  • 打赏
  • 举报
回复
引用 9 楼 u014699391 的回复:
还好没有完全相信那本书的内容,学习了,请问下这方面的知识要如何系统的学习?
1。平时多注意、多积累 2。尽量跟着标准走 3。不要依赖于手头上具体的编译器、开发环境等。虽然这可能是你考试或吃饭的东西,但是换过来想一想,舍不得芝麻而丢了西瓜,是不是更不值得 4。完备的教材还是需要的,不一定要多有名,但是至少知识点要覆盖较完全、而且不能有重大错误。不过考虑到当前国内的大环境,这点上不好多说什么了。。
赵4老师 2014-05-20
  • 打赏
  • 举报
回复
引用 10 楼 u014699391 的回复:
[quote=引用 8 楼 zhao4zhong1 的回复:] 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
有时候运行结果也会骗人,不同的编译器编译出来的结果都不本样。[/quote] 大自然从来没骗过人,只是人以为1+1应该等于2,大自然从来就没实际发生过哪怕一次未来也不会发生哪怕一次1+1=2!
_skytrails 2014-05-20
  • 打赏
  • 举报
回复
引用 8 楼 zhao4zhong1 的回复:
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
有时候运行结果也会骗人,不同的编译器编译出来的结果都不本样。
_skytrails 2014-05-20
  • 打赏
  • 举报
回复
引用 5 楼 unituniverse2 的回复:
[quote=引用 4 楼 u014699391 的回复:] [quote=引用 3 楼 ilikehigame 的回复:] 246?????
很接近了,可以说下你是怎么想的吗?书上的答案是250(用vc2008编译的),但我在gcc上编译的是2.这两个怎么会不一样?[/quote] 整型提升问题。 这是因为vc的不标准。 整型提升要求被提升的整数应该是个纯右值(prvalue),而纯右值必须是值(而不能是引用,否则就叫xvalue),而且必须是右值(临时变量)。可能制定标准的人认为只有复杂表达式才需要做这种提升,简单表达式(几乎没有机会产生prvalue)也做的话会导致复杂难用。 vc做提升的时候没有考虑左右值的问题。就你给的例子: b = ~a >> (4 + 1) a是个左值,所以按标准不允许提升,所以只能先直接取反(然后得到的结果才是右值),于是表达式计算过程: ~a=0x5a(注意整个~a的计算结果是个右值,而a不是); 0x00000004+0x00000001=0x00000005(右值) =〉(unsigned int)(int)0x5a >> 0x00000005得到 0x0000005a >> 0x00000005等于0x00000002都是int型的,最后赋值给左值b,相当于 b=(unsigned char)0x00000002, 所以结果b为0x02; 再看vc,因为没有考虑左右值问题而直接提升了, a=0xa5 => ~a = ~(unsigned int)(int)0xa5 = ~0x000000a5 = 0xffffff5a; 0x00000004+0x00000001=0x00000005 =〉0xffffff5a >> 0x00000005等于0xfffffffa,最后赋值给左值b,相当于 b=(unsigned char)0xfffffffa,所以结果b为0xfa 如果想达到行为一致的话,

unsigned char a = 0xA5; 
unsigned char b = (unsigned char)~a >> (4 + 1);
printf("b=%d\n",b);
可能你会问了,要是每个表达式含有按位取反的都像这样强转一下那会不会很麻烦?一般不会的,只有~混合了右移位操作的才需要。[/quote]还好没有完全相信那本书的内容,学习了,请问下这方面的知识要如何系统的学习?
杀意已决 2014-05-19
  • 打赏
  • 举报
回复
引用 2 楼 u014699391 的回复:
[quote=引用 1 楼 boxmanstan 的回复:] 先>> 再~再+1 10100101 00001010 10001010 10001011 10001100 忘光了,不知道对没对,有点心虚
哈哈,错了,先~再+再>>,仔细看下运算符优先表![/quote] 喃妈大
unituniverse2 2014-05-19
  • 打赏
  • 举报
回复
引用 4 楼 u014699391 的回复:
[quote=引用 3 楼 ilikehigame 的回复:] 246?????
很接近了,可以说下你是怎么想的吗?书上的答案是250(用vc2008编译的),但我在gcc上编译的是2.这两个怎么会不一样?[/quote] 整型提升问题。 这是因为vc的不标准。 整型提升要求被提升的整数应该是个纯右值(prvalue),而纯右值必须是值(而不能是引用,否则就叫xvalue),而且必须是右值(临时变量)。可能制定标准的人认为只有复杂表达式才需要做这种提升,简单表达式(几乎没有机会产生prvalue)也做的话会导致复杂难用。 vc做提升的时候没有考虑左右值的问题。就你给的例子: b = ~a >> (4 + 1) a是个左值,所以按标准不允许提升,所以只能先直接取反(然后得到的结果才是右值),于是表达式计算过程: ~a=0x5a(注意整个~a的计算结果是个右值,而a不是); 0x00000004+0x00000001=0x00000005(右值) =〉(unsigned int)(int)0x5a >> 0x00000005得到 0x0000005a >> 0x00000005等于0x00000002都是int型的,最后赋值给左值b,相当于 b=(unsigned char)0x00000002, 所以结果b为0x02; 再看vc,因为没有考虑左右值问题而直接提升了, a=0xa5 => ~a = ~(unsigned int)(int)0xa5 = ~0x000000a5 = 0xffffff5a; 0x00000004+0x00000001=0x00000005 =〉0xffffff5a >> 0x00000005等于0xfffffffa,最后赋值给左值b,相当于 b=(unsigned char)0xfffffffa,所以结果b为0xfa 如果想达到行为一致的话,

unsigned char a = 0xA5;
unsigned char b = (unsigned char)~a >> (4 + 1);
printf("b=%d\n",b);
可能你会问了,要是每个表达式含有按位取反的都像这样强转一下那会不会很麻烦?一般不会的,只有~混合了右移位操作的才需要。
赵4老师 2014-05-19
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
LAN_YT 2014-05-19
  • 打赏
  • 举报
回复
引用 5 楼 unituniverse2 的回复:
[quote=引用 4 楼 u014699391 的回复:] [quote=引用 3 楼 ilikehigame 的回复:] 246?????
很接近了,可以说下你是怎么想的吗?书上的答案是250(用vc2008编译的),但我在gcc上编译的是2.这两个怎么会不一样?[/quote] 整型提升问题。 这是因为vc的不标准。 整型提升要求被提升的整数应该是个纯右值(prvalue),而纯右值必须是值(而不能是引用,否则就叫xvalue),而且必须是右值(临时变量)。可能制定标准的人认为只有复杂表达式才需要做这种提升,简单表达式(几乎没有机会产生prvalue)也做的话会导致复杂难用。 vc做提升的时候没有考虑左右值的问题。就你给的例子: b = ~a >> (4 + 1) a是个左值,所以按标准不允许提升,所以只能先直接取反(然后得到的结果才是右值),于是表达式计算过程: ~a=0x5a(注意整个~a的计算结果是个右值,而a不是); 0x00000004+0x00000001=0x00000005(右值) =〉(unsigned int)(int)0x5a >> 0x00000005得到 0x0000005a >> 0x00000005等于0x00000002都是int型的,最后赋值给左值b,相当于 b=(unsigned char)0x00000002, 所以结果b为0x02; 再看vc,因为没有考虑左右值问题而直接提升了, a=0xa5 => ~a = ~(unsigned int)(int)0xa5 = ~0x000000a5 = 0xffffff5a; 0x00000004+0x00000001=0x00000005 =〉0xffffff5a >> 0x00000005等于0xfffffffa,最后赋值给左值b,相当于 b=(unsigned char)0xfffffffa,所以结果b为0xfa 如果想达到行为一致的话,

unsigned char a = 0xA5;
unsigned char b = (unsigned char)~a >> (4 + 1);
printf("b=%d\n",b);
可能你会问了,要是每个表达式含有按位取反的都像这样强转一下那会不会很麻烦?一般不会的,只有~混合了右移位操作的才需要。[/quote] 专业,Orz
_skytrails 2014-05-18
  • 打赏
  • 举报
回复
引用 3 楼 ilikehigame 的回复:
246?????
很接近了,可以说下你是怎么想的吗?书上的答案是250(用vc2008编译的),但我在gcc上编译的是2.这两个怎么会不一样?
  • 打赏
  • 举报
回复
246?????
_skytrails 2014-05-18
  • 打赏
  • 举报
回复
引用 1 楼 boxmanstan 的回复:
先>> 再~再+1 10100101 00001010 10001010 10001011 10001100 忘光了,不知道对没对,有点心虚
哈哈,错了,先~再+再>>,仔细看下运算符优先表!
杀意已决 2014-05-18
  • 打赏
  • 举报
回复
先>> 再~再+1 10100101 00001010 10001010 10001011 10001100 忘光了,不知道对没对,有点心虚

64,652

社区成员

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

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