C语言 同行与多行逐位操作差异

ioekq8ef  于 2023-02-11  发布在  其他
关注(0)|答案(2)|浏览(135)

在为uni写程序的时候,我注意到

unsigned char byte_to_write_1 = (0xFF << 2) >> 2; ==> 0xFF (wrong)
unsigned char byte_to_write_2 = (0xFF << 2);
byte_to_write_2 = byte_to_write_2 >> 2; ==> 0x3F (correct)

我不明白是什么导致了这种差异......我最好的猜测是,当在同一行上用多个操作修改一个字节时,C会“保留”稍大的数据类型中的额外位,直到该行终止,因此0xFF〈〈2被保留为11[1111 1100],而不是1111 1100,因此在同一行上的回移,结果是1111111而不是11111100。
是什么导致结果的差异?提前感谢...
我第一次注意到这个问题是在一个更大的代码项目中,但我已经能够使用一个简单得多的程序重现这个问题。image of simplified code to showcase problem

px9o7tmv

px9o7tmv1#

unsigned char byte_to_write_1 = (0xFF << 2) >> 2;  // 0xFF

0xFF是一个int。(从unsigned char获得0xFF不会改变任何东西,因为它将被提升为int。)0xFF << 20x3FC0x3FC >> 20xFF

unsigned char byte_to_write_2 = 0xFF << 2;  // 0xFC
byte_to_write_2 >>= 2;                      // 0x3F

我们已经确定了0xFF << 20x3FC,但是你把它赋给了一个unsigned char,而这个unsigned char大概只有8位大小,所以你最后把它赋给了0xFC(如果你启用了警告功能,gcc会发出警告)。
当然,当你把它右移的时候,你会得到想要的值。
解决方案:
一个一个二个一个一个一个三个一个一个一个一个一个四个一个
Demo(位于编译器资源管理器上)。

jgovgodb

jgovgodb2#

这两个代码段之间的区别

unsigned char byte_to_write_1 = (0xFF << 2) >> 2; ==> 0xFF (wrong)

以及

unsigned char byte_to_write_2 = (0xFF << 2);
byte_to_write_2 = byte_to_write_2 >> 2; ==> 0x3F (correct)

在第二段代码中,使用变量byte_to_write_2来存储表达式(0xFF << 2)的中间结果,该变量不能保存完整的整数结果,因此将整数结果转换为只能存储一个字节的类型unsigned char
unsigned character类型的对象中可存储的最大值为0xFF

— maximum value for an object of type unsigned char
UCHAR_MAX 255 // 28 − 1

而等价于255 * 4的表达式0xFF << 2不能适合类型为unsigned char的对象。
在第一个代码片段中,由于整数提升,表达式(0xFF << 2)的中间结果具有类型int,并且可以在不更改完整表达式(0xFF << 2) >> 2的情况下使用。
考虑printf的这两个调用的输出

printf( "0xFF << 2 = %d\n", 0xFF << 2 );
printf( "( unsigned char )( 0xFF << 2 ) = %d\n", ( unsigned char )( 0xFF << 2 ) );

他们是

0xFF << 2 = 1020
( unsigned char )( 0xFF << 2 ) = 252

相关问题