应用于 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;
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;