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

C binary operator applyed on width of LVALUE or 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 标准这是正确的行为?

在等待您 post 您发现这两个代码片段的编译方式有何不同时,(因为我的评论似乎促使您想到一个答案,但我不是确保这是正确的答案,)我只想说可能发生的事情是这样的:

指令 Variable._Data &= ~3uL; 导致无符号长字面量与长值进行“与”运算。

指令Variable._Data &= ~3u;采用无符号(长)字面量,将其零扩展为长,然后与长值进行AND运算。

因此,这些指令的编译方式可能不同,这很可能是由于您在正确的操作数中声明文字的方式不同。这可能与左操作数无关,也与您在操作数之间执行的操作无关。

无论如何,在这一点上,这是我的猜测;请 post 您对这两个代码片段的编译方式有何不同的确切发现,我可能会修改我的答案。

不是bug,这两个表达式不相等:

Variable._Data &= ~3uL;

Variable._Data &= ~3u;

两者都会将最低有效两位清零。但只有第二个会将最重要的 16 位清零。请记住,在您的机器上,类型 int 的宽度为 16 位,而 long 的宽度为 32 位。

一元运算符 ~ 将在执行 &= 操作之前应用于整数文字。差异(在您的机器上)是:

操作 ~3LU 结果:0xFFFFFFFC

操作 ~3U 结果:0xFFFC 然后提升为 long:0x0000FFFC

将这两个值应用于 Variable._Data 的结果与上述不同。

第一个是:

Variable._Data &= 0xFFFFFFFC;

第二个是:

Variable._Data &= 0x0000FFFC;