有什么办法可以抑制 gcc 在此代码中生成的警告:
int main() {
struct flagstruct {
unsigned flag : 1;
} a,b,c;
a.flag = b.flag | c.flag;
return a.flag;
}
警告是
warning: conversion to 'unsigned char:1' from 'int' may alter its value [-Wconversion]
看起来这两个标志在一起运算时被扩展为 int 。
我认为真正奇怪的是,将两个标志中的任何一个转换为 unsigned 都会抑制警告。
a.flag = (unsigned)b.flag | c.flag;
这是编译器错误还是应该以这种方式工作?
看起来这两个标志在一起运算时被扩展为 int 。
This is 整数提升它在 C99 标准的措辞奇怪的条款 6.3.1.1:2 中定义:
当 int 或 unsigned 的表达式中可以使用以下内容
可以使用 int:
…
— _Bool、int、signed int 或 unsigned int 类型的位字段。如果
int可以表示原始类型的所有值,其值为
转换为 int;否则,它被转换为无符号整型。
这些称为整数促销。所有其他类型均不变
通过整数促销。
首先,处理器不直接在位域上计算,并且可能也没有在较窄的整数类型上计算的指令char
and short
。 C 标准通过仅定义算术运算来捕获这一点int
, unsigned int
和更广泛的整数类型。上面的标准说“可以使用”,它试图(糟糕地)表达这一点all短类型和位字段必须提升为int
or unsigned int
在参与算术之前。
其次,所有宽度不足以包含无法表示为的值的无符号位字段int
被提升为int
。
换句话说,GCC 通过将未签名的位字段提升为签名来按照标准行事int
,并像您所做的那样添加明确的演员阵容,似乎是防止未来出现意外情况(以及反对警告)的最佳策略。
我认为真正奇怪的是,将两个标志中的任何一个转换为 unsigned 都会抑制警告。
常见的算术转换,C 标准中的另一个有趣的概念(C99 中的 6.3.1.8),其结果是,如果两个操作数中的任何一个显式转换为unsigned int
,那么这次另一个操作数也隐式转换为unsigned int
和|
操作是一个unsigned int
操作生产unsigned int
result.
换句话说,(unsigned)b.flag | c.flag
严格等价于(unsigned)b.flag | (unsigned)c.flag
。在这种情况下,编译器认为没有理由警告赋值,因为计算结果是unsigned int
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)