如果一个整数默认是有符号的,为什么会存在 signed 关键字?

If an integer is signed by default, why does the signed keyword exist?

我很好奇为什么存在 signed 关键字,因为我相信大多数整数和其他变量在默认情况下都是有符号的。将 signed 关键字放在 int 之前几乎没有任何作用。它有什么用,为什么存在?

至少有两个地方 signed 关键字不是空操作:

  • With char: "plain" char 的符号是实现定义的。在它是无符号类型的实现中,需要 signed char 才能获得带符号的变体。即使 char 是有符号类型,signed charcharunsigned char 都是不同的类型。

  • 使用位域:没有显式签名的位域成员具有实现定义的签名。例如,在

    struct foo {
        int b:1;
    };
    

    b 的取值范围可能是 { -1, 0 } 或 { 0, 1 },具体取决于实现。如果您想确保获得签名版本,则需要 signed 关键字。请注意,虽然标准对此不是很清楚,但在流行的实现中,这也适用于 typedef:如果位域成员使用不包含显式签名的 typedef 定义的类型,则实现-定义的签名(在 GCC 上,由 -fsigned-bitfields 设置)也适用于此。这意味着像 int32_t 这样的类型应该使用 signed 关键字来定义,以避免在位域中使用时出现非常糟糕的意外行为。

char 要么是有符号的,要么是无符号的,但无论如何它是一种不同于 unsigned charsigned char 的类型。这三个是不同的类型:

char
signed char
unsigned char

如果不使用 signed,则需要一些其他方法来区分它们。

即使没有char。为什么不?它允许明确:

signed int x; // Someone decided that x 
              // must be signed
int y;        // Did the author choose signed 
              // consciously? We cannot tell.