12

我通常可以理解编译器警告背后的原因,但这似乎完全是错误的。

#include <stdint.h>    
uint8_t myfunc(uint8_t x,uint8_t y)
{
    x |= y;
    return x;
}

带有 -Wall 的英特尔编译器抱怨:

conversion from "int" to "uint8_t={unsigned char}" may lose significant bits
  x |= y;
    ^

这是正确的吗?上面的代码在某种程度上是不可移植和非标准的吗?

4

4 回答 4

9

那是integer promotions在工作。

x |= y;

运算符的两个操作数|都提升为int

x = (int)x | (int)y;

然后将结果转换回uint8_t失去精度。

于 2011-05-03T14:51:24.270 回答
5

这是正确的。运算符将参数提升为int。有关更多详细信息,请参阅此页面,第一句话开始:

C 没有以比 int [...] 更短的精度完成算术运算

于 2011-05-03T14:49:20.557 回答
4

x和的值y被提升为int用于计算,但警告仍然是虚假的。|运算符不能将结果的宽度(以位为单位)增加到超出操作数的宽度,因为uint8_t它们从uint8_t. 此警告选项标记的绝大多数内容都是完全有效且正确的代码,除非您想在 100 个这样的问题上浪费时间,否则我认为最好关闭或忽略这些警告。

于 2011-05-03T14:54:09.820 回答
1

编译器警告可能看起来很荒谬,因为该操作不可能产生超过 8 位,但它只是可以产生的更大类操作的一个子集。例如,如果您将 替换为|=+=溢出的可能性就变得非常真实。

消除警告的方法是告诉编译器您有意识地用强制转换丢弃这些位:

x = (uint8_t)(x | y);
于 2011-05-03T15:19:03.457 回答