GCC将uint8_t和uint16_t解释为带符号吗?

时间:2019-04-30 03:38:14

标签: linux c++11 gcc

我的测试代码:

#include <cstdint>
#include <cstdio>

int main() {
    const constexpr uint8_t x = 64;
    printf("%u", x);
}

这是我使用GCC 8.2进行编译的方式:

g++ -Wall test_format.cpp -o test_format -O3 -std=c++17 -Wformat-signedness

这是GCC的输出:

test_format.cpp: In function ‘int main()’:
test_format.cpp:6:9: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
  printf("%u", x);
         ^~~~

如果我尝试打印uint32_t,它没有错误/警告。

我想知道为什么GCC希望uint8_t被完整地签名。

谢谢。

3 个答案:

答案 0 :(得分:1)

Default argument promotions应用于可变函数的操作数。在这些条件下,类型unsigned char的表达式被提升为int

答案 1 :(得分:1)

在C和C ++中,比int窄的类型总是提升为int。参见Why must a short be converted to an int before arithmetic operations in C and C++?

内部可变参数函数中的默认提升也适用,这意味着您不能将比int窄的类型传递给vararg函数。因此uint8_t必须用%d而不是%u打印。但是无论如何,您打印的方式都是错误的。正确的方法是使用PRIu8

printf("%" PRIu8 "\n", x);

答案 2 :(得分:0)

要使用uint8_t打印printf()变量,应执行以下操作:

#include <cinttypes>
#include <cstdio>

int print_u8(std::uint8_t x) {
  return std::printf("%" PRIu8 "\n", x);
}

<cinttypes>标头包含应用于最大可移植性的所有<cstdint>类型的printf和scanf格式说明符(并显式包括该标头)。