TL;DR
1、3、4 在存在 intN_t 的任何 C99、C11 编译器上都为真。 2 在存在 int8_t 的任何 C11 编译器上都为真 - 因为 int8_t 的存在意味着 CHAR_BIT 为 8。 5 特别不需要 C -有符号整数溢出的行为未定义。
POSIX 限制了允许的 C 实现,因此 CHAR_BIT 必须为 8 并且整数表示是二进制补码。因此,在 POSIX 平台上兼容的 C99/C11 编译器必须具有 int8_t,这使得语句 1、2、3 和 4 在 POSIX 上为真。由于 POSIX 没有说明有符号整数溢出,它仍然是未定义的,因此 5 为假。
引用的句子逐字取自 C11 (C99) 标准。 C11 7.20.1.1p1:
typedef 名称intN_t 指定一个有符号整数类型,宽度为N,没有填充位,并且是二进制补码表示。因此,int8_t 表示这种有符号整数类型,宽度正好为 8 位。
int8_t 在 C 中是可选,因此仅在标准中存在此片段甚至不需要 2 的补码表示。 C11 7.20.1.1p3:
这些类型是可选的。但是,如果实现提供了宽度为 8、16、32 或 64 位的整数类型,没有填充位,并且(对于有符号类型)具有二进制补码表示,则它应定义相应的 typedef 名称。
在您的原始陈述中,
当然是正确的,但这种情况并不能从 二的补码表示中得出。 int 范围从 INT_MIN 到 INT_MAX 在任何人的补码架构上也是如此。但是,由此得出的结论是 INTN_MIN 的值是 。
不遵循补码表示。 sizeof(intN_t) 是 N / CHAR_BIT。但是,POSIX 要求 CHAR_BIT 是 8 所以 sizeof(intN_t) 确实是 N / 8
这是二进制补码表示
的唯一内容
不遵循二进制补码表示,而是 2 的补码的组合并且没有填充位。
-
不遵循二进制补码表示,C 和 POSIX 都不需要。
int8_t 类型不是 POSIX 指定的,而是 POSIX 采用和扩充的 C99、C11。 POSIX 增加了两个限制:
* CHAR_BIT 必须正好为 8 且不能更大,即使 C 编程语言允许
* 不允许整数的补码或符号和大小表示,即使 C 编程语言允许这样做
C99、C11 指定如果存在,类型intN_t 必须有这么多位且没有填充位和2 的补码。如果int8_t存在,那么它的sizeof必须是1,因为它是signed char的同义词,而CHAR_BIT等于8。
intN_t 不会有陷阱表示,但这并不意味着那些具有明确 indeterminate 值的对象必须具有相同的值,或者将这些值传递给库函数将具有定义的行为。考虑以下片段:
int32_t *foo = malloc(sizeof(int32_t));
printf(PRId32 "\n", *foo);
printf(PRId32 "\n", *foo);
free(foo);
编译器甚至不需要调用malloc;它可以将其编译为等效于puts("42\n666"); - 即使没有int32_t 类型的陷阱值。这是因为malloc:
[...] 为大小由 size 指定且 其值不确定 的对象分配空间。
不确定真的意味着unstable; indeterminable
有符号整数溢出的行为始终未定义。