POSIX在stdint.h中的"two's complement representation"是什么意思?
What does POSIX mean by "two's complement representation" in stdint.h?
众所周知,有符号整数溢出会引发未定义的行为,并且有符号整数的按位操作充其量是不可靠的。因此,我发现 the POSIX standard 中的这一行相当奇怪:
The typedef name int N _t designates a signed integer type with width N, no padding bits, and a two's-complement representation. Thus, int8_t denotes a signed integer type with a width of exactly 8 bits.
这是一个相当模糊的陈述,可能意味着这些事情的任意组合:
intN_t
的范围是INTN_MIN
到INTN_MAX
。
sizeof(intN_t) == N/8
intN_t
上的按位运算按照二进制补码表示的预期方式运行。 -1 ^ x == ~x
对于每个 x
,在到处插入 intN_t
转换之后。
intN_t
不能有陷阱表示(并且优化编译器不能利用可能的陷阱)。
intN_t
变量的溢出是已定义的行为(并从 INTN_MAX
回绕到 INTN_MIN
)。
根据文档的其余部分,(1) 和 (2) 对我来说显然都是正确的。 (1) 由 INTN_MIN
/MAX
的定义明确指定。 (2) 隐含于 "no padding bits."
POSIX 要求 (3)、(4) 和 (5) 中的哪一个?
TL;DR
1、3、4 在任何 C99、C11 编译器上都是正确的,其中 intN_t
存在。 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:
The typedef name intN_t
designates a signed integer type with width N
, no padding bits, and a two's complement representation. Thus, int8_t
denotes such a signed integer type with a width of exactly 8 bits.
int8_t
在 C 中是 optional,因此标准中仅存在此片段甚至不需要 2 的补码表示。 C11 7.20.1.1p3:
These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two's complement representation, it shall define the corresponding typedef names.
在您的原始陈述中,
当然是对的,但是从二的补码表示就不能得出这样的结论。 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 且不能大于 8,即使 C 编程语言允许
* 整数的补码或符号和大小表示是不允许的,即使 C 编程语言允许它们
C99、C11 指定 如果存在 ,类型 intN_t
必须有这么多位,没有填充位和 2 的补码。如果int8_t
存在,它的sizeof
一定是1,因为它是signed char
then的同义词,CHAR_BIT
等于8。
不会有 intN_t
的陷阱表示,但这并不意味着那些 不确定 值的对象必须具有相同的值,或者将这些值传递给库函数将具有定义的行为。考虑以下片段:
int32_t *foo = malloc(sizeof(int32_t));
printf(PRId32 "\n", *foo);
printf(PRId32 "\n", *foo);
free(foo);
编译器甚至不需要调用malloc
;它可以将其编译为 puts("42\n666");
的等价物——即使没有 int32_t
类型的陷阱值。这是因为 malloc
:
[...] allocates space for an object whose size is specified by size and whose value is indeterminate.
不确定的真正意思是unstable; indeterminable
有符号整数溢出的行为始终未定义。
众所周知,有符号整数溢出会引发未定义的行为,并且有符号整数的按位操作充其量是不可靠的。因此,我发现 the POSIX standard 中的这一行相当奇怪:
The typedef name int N _t designates a signed integer type with width N, no padding bits, and a two's-complement representation. Thus, int8_t denotes a signed integer type with a width of exactly 8 bits.
这是一个相当模糊的陈述,可能意味着这些事情的任意组合:
intN_t
的范围是INTN_MIN
到INTN_MAX
。sizeof(intN_t) == N/8
intN_t
上的按位运算按照二进制补码表示的预期方式运行。-1 ^ x == ~x
对于每个x
,在到处插入intN_t
转换之后。intN_t
不能有陷阱表示(并且优化编译器不能利用可能的陷阱)。intN_t
变量的溢出是已定义的行为(并从INTN_MAX
回绕到INTN_MIN
)。
(1) 和 (2) 对我来说显然都是正确的。 (1) 由 INTN_MIN
/MAX
的定义明确指定。 (2) 隐含于 "no padding bits."
POSIX 要求 (3)、(4) 和 (5) 中的哪一个?
TL;DR
1、3、4 在任何 C99、C11 编译器上都是正确的,其中 intN_t
存在。 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:
The typedef name
intN_t
designates a signed integer type with widthN
, no padding bits, and a two's complement representation. Thus,int8_t
denotes such a signed integer type with a width of exactly 8 bits.
int8_t
在 C 中是 optional,因此标准中仅存在此片段甚至不需要 2 的补码表示。 C11 7.20.1.1p3:
These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two's complement representation, it shall define the corresponding typedef names.
在您的原始陈述中,
当然是对的,但是从二的补码表示就不能得出这样的结论。
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 且不能大于 8,即使 C 编程语言允许
* 整数的补码或符号和大小表示是不允许的,即使 C 编程语言允许它们
C99、C11 指定 如果存在 ,类型 intN_t
必须有这么多位,没有填充位和 2 的补码。如果int8_t
存在,它的sizeof
一定是1,因为它是signed char
then的同义词,CHAR_BIT
等于8。
不会有 intN_t
的陷阱表示,但这并不意味着那些 不确定 值的对象必须具有相同的值,或者将这些值传递给库函数将具有定义的行为。考虑以下片段:
int32_t *foo = malloc(sizeof(int32_t));
printf(PRId32 "\n", *foo);
printf(PRId32 "\n", *foo);
free(foo);
编译器甚至不需要调用malloc
;它可以将其编译为 puts("42\n666");
的等价物——即使没有 int32_t
类型的陷阱值。这是因为 malloc
:
[...] allocates space for an object whose size is specified by size and whose value is indeterminate.
不确定的真正意思是unstable; indeterminable
有符号整数溢出的行为始终未定义。