C 将无符号转换为有符号是如何工作的?
How does C casting unsigned to signed work?
标准中的哪种语言使此代码有效,打印“-1”?
unsigned int u = UINT_MAX;
signed int s = u;
printf("%d", s);
https://en.cppreference.com/w/c/language/conversion
otherwise, if the target type is signed, the behavior is implementation-defined (which may include raising a signal)
https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation
GCC supports only two’s complement integer types, and all bit patterns are ordinary values.
The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 and C11 6.3.1.3):
For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised.
对我来说,将 UINT_MAX
转换为 int
似乎意味着将 UINT_MAX
除以 2^(CHAR_BIT * sizeof(int))
。为了争论,使用 32 位整数,0xFFFFFFFF / 2^32 = 0xFFFFFFFF
。所以这并不能真正解释值 '-1' 如何在 int
.
中结束
其他地方是否有某种语言说在模除法之后我们只是重新解释这些位?还是优先于我引用的部分的标准的其他部分?
C 标准的任何部分都不能保证您的代码通常会打印 -1。正如它所说,转换的结果是实现定义的。但是,GCC 文档确实承诺,如果您使用它们的实现进行编译,那么您的代码将打印 -1。这与位模式无关,只是数学。
GCC 手册中“reduced modulo 2^N”的明确意图是结果应该是 signed int
范围内的唯一数字,与 [=23 一致=] 2^N 到输入。这是定义您期望的“包装”行为的精确数学方法,恰好与您通过重新解释位得到的结果一致。
假设 32 位,UINT_MAX
的值为 4294967295。这与 mod 4294967296 对应 -1。即4294967295与-1之差是4294967296的倍数,即4294967296本身。此外,这必然是 [-2147483648, 2147483647] 中唯一的此类数字。 (与 -1 一致的任何其他数字至少为 -1 + 4294967296 = 4294967295
,或至多为 -1 - 4294967296 = -4294967297
)。所以-1就是转换后的结果。
换句话说,反复加减4294967296,直到得到一个在signed int
范围内的数字。保证只有一个这样的数字,在本例中为 -1。
标准中的哪种语言使此代码有效,打印“-1”?
unsigned int u = UINT_MAX;
signed int s = u;
printf("%d", s);
https://en.cppreference.com/w/c/language/conversion
otherwise, if the target type is signed, the behavior is implementation-defined (which may include raising a signal)
https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation
GCC supports only two’s complement integer types, and all bit patterns are ordinary values.
The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 and C11 6.3.1.3):
For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised.
对我来说,将 UINT_MAX
转换为 int
似乎意味着将 UINT_MAX
除以 2^(CHAR_BIT * sizeof(int))
。为了争论,使用 32 位整数,0xFFFFFFFF / 2^32 = 0xFFFFFFFF
。所以这并不能真正解释值 '-1' 如何在 int
.
其他地方是否有某种语言说在模除法之后我们只是重新解释这些位?还是优先于我引用的部分的标准的其他部分?
C 标准的任何部分都不能保证您的代码通常会打印 -1。正如它所说,转换的结果是实现定义的。但是,GCC 文档确实承诺,如果您使用它们的实现进行编译,那么您的代码将打印 -1。这与位模式无关,只是数学。
GCC 手册中“reduced modulo 2^N”的明确意图是结果应该是 signed int
范围内的唯一数字,与 [=23 一致=] 2^N 到输入。这是定义您期望的“包装”行为的精确数学方法,恰好与您通过重新解释位得到的结果一致。
假设 32 位,UINT_MAX
的值为 4294967295。这与 mod 4294967296 对应 -1。即4294967295与-1之差是4294967296的倍数,即4294967296本身。此外,这必然是 [-2147483648, 2147483647] 中唯一的此类数字。 (与 -1 一致的任何其他数字至少为 -1 + 4294967296 = 4294967295
,或至多为 -1 - 4294967296 = -4294967297
)。所以-1就是转换后的结果。
换句话说,反复加减4294967296,直到得到一个在signed int
范围内的数字。保证只有一个这样的数字,在本例中为 -1。