困惑的编译器警告表明int8_t的复合赋值提升为int

Mar*_*ing 12 c c++ standards icc

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

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

带-Wall的intel编译器抱怨:

conversion from "int" to "uint8_t={unsigned char}" may lose significant bits
  x |= y;
    ^
Run Code Online (Sandbox Code Playgroud)

这是正确的吗?上面的代码是否是非便携式和非标准的?

pmg*_*pmg 9

那是integer promotions在起作用.

x |= y;
Run Code Online (Sandbox Code Playgroud)

|运营商的两个操作数都被提升为int

x = (int)x | (int)y;
Run Code Online (Sandbox Code Playgroud)

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

  • 警告说"可能会失去重要的一部分".那是明显错误的.此操作不会丢失任何位. (4认同)
  • 如果您不遵守GNU编码标准来进行大括号缩放,编译器当然可以自由发出警告,但大多数用户会发现令人难以置信的烦恼和错误.同样,这个警告是错误的.它只是盲目地查看表达式的*类型*,而不是表达式*的可能范围*来发出警告.如果它使用后者,这将更有意义,它很容易看到潜在的值范围是0-255并关闭. (4认同)
  • @R ..:这比这里的范围分析(可能需要流量分析)更容易,gcc可以实现比一些运算符(`|`,`^`,`&`)不增加值的范围,因此那个`uint8_t | uint8_t`必然适合`uint8_t`.似乎他们将此分析推迟到以后(在类型推广之后)并且没有考虑到这一点......当然我也会支持任何形式的轻量级范围分析,但它要复杂得多:) (3认同)

unw*_*ind 5

这是正确的.运营商将论证提升为int.有关详细信息,请参阅此页面,第一句开头:

C的精度不低于int [...]