C如何处理二元运算符?标准是否要求编译器将其转换为LVALUE或不需要它?
我发现的具体问题如下:
typedef union {
unsigned long _Data;
struct {
unsigned long _Reserved : 28;
unsigned long _Info : 1;
unsigned long _Reserved2 : 3;
};
} S_INFO;
S_INFO Variable;
使用这些定义,指令
Variable._Data &= ~3uL;
编译与指令不同
Variable._Data &= ~3u;
在16位架构中,int为2字节宽,long为4字节宽。
编译器似乎应用&运算符到文字的宽度(RVALUE),而不是LVALUE Variable._Data的宽度。
我是否发现了编译器错误或根据C标准这是正确的行为?
答案 0 :(得分:0)
在等待你发表关于两个代码片段编译方式不同的发现时(并且因为我的评论似乎促使你想到答案,但我不确定这是否正确回答,)我只想说可能发生的事情就是:
指令Variable._Data &= ~3uL;
导致无符号长文字与长值进行AND运算。
指令Variable._Data &= ~3u;
采用无符号( not long)字面值,将其零扩展为long,然后使用long值对其进行AND运算。
因此,这些指令的编译方式可能不同,这可能是由于您在右操作数中声明文字的方式。这可能与左操作数无关,也与操作数之间的操作无关。
无论如何,在这一点上,这是我的猜测;请发表您的调查结果,确切地说两个代码片段的编译方式不同,我可以修改我的答案。
答案 1 :(得分:0)
这不是一个错误,这两个表达式不相等:
Variable._Data &= ~3uL;
Variable._Data &= ~3u;
两者都会将最不重要的两位清零。但只有第二个会将最重要的16位清零。请记住,在您的机器上,int类型的宽度为16位,宽度为32位。
在执行~
操作之前,将对整数文字应用一元&=
运算符。差异(在您的机器上)是:
操作~3LU导致:0xFFFFFFFC
操作~3U导致:0xFFFC然后被提升为long:0x0000FFFC
如上所述,在Variable._Data
上应用这两个值的结果是不同的。
首先是:
Variable._Data &= 0xFFFFFFFC;
,第二个是:
Variable._Data &= 0x0000FFFC;