C二元运算符应用于LVALUE或RVALUE

时间:2016-09-27 10:04:18

标签: c casting binary rvalue

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标准这是正确的行为?

2 个答案:

答案 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;