c 标准是否保证有符号和无符号的位模式解释?
C 标准是否规定了应如何解释位表示?换句话说,以下 if 条件总是评估为 true 吗?假设 sizeof (int) = 4 且 CHAR_BIT = 8
unsigned u = 0xffffffff;
if (u == 4294967295) /* do something */
int i = 0xffffffff;
if (i == -1) /* do something */
unsigned u = (int)0xffffffff;
if (u == 0xffffffff) /* do something */
int i = hex_literal;
unsigned u;
memcpy (&u, &i, sizeof (u));
if (i == u) /* do something */
if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */
int i = hex_literal;
unsigned u = i;
if (i == u) /* do something */
unsigned u = hex_literal;
int i = u;
if (i == u) /* do something */
int i = hex_literal;
unsigned u = hex_literal;
if (i == hex_literal && u == hex_literal) /* do something */
char c = 0xff;
if (c >> 4 == 0xf) /* do something */
signed char c = 0xff;
if (((c >> 4) & 0xff) == 0xf) /* do something */
Does the C standard state how bit representations should be interpreted? In other words do the following if conditions always evaluate to true? Assume sizeof (int) = 4 and CHAR_BIT = 8
unsigned u = 0xffffffff;
if (u == 4294967295) /* do something */
int i = 0xffffffff;
if (i == -1) /* do something */
unsigned u = (int)0xffffffff;
if (u == 0xffffffff) /* do something */
int i = hex_literal;
unsigned u;
memcpy (&u, &i, sizeof (u));
if (i == u) /* do something */
if ((i & 0x7fffffff) == (u & 0x7fffffff)) /* do something */
int i = hex_literal;
unsigned u = i;
if (i == u) /* do something */
unsigned u = hex_literal;
int i = u;
if (i == u) /* do something */
int i = hex_literal;
unsigned u = hex_literal;
if (i == hex_literal && u == hex_literal) /* do something */
char c = 0xff;
if (c >> 4 == 0xf) /* do something */
signed char c = 0xff;
if (((c >> 4) & 0xff) == 0xf) /* do something */
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我将做出额外的假设,即所讨论的实现中没有任何类型具有填充位。让我们一次一个地讲:
是的。
不会。将超出范围的数字转换为有符号类型会给出实现定义的结果。
不,原因与前面的示例相同。
是的。该标准保证有符号类型中的每个值位在相应无符号类型的对象表示中具有相同的值。
是的。
i
从int
到unsigned
的提升是确定性的,并且在对u
和u
的赋值中产生相同的值在比较中。是的,但前提是
hex_literal
位于由int
表示的(正)值范围内 - 否则实现定义的结果会再次出现。u == hex_literal
将始终评估为 true,但i == hex_literal
仅当hex_literal
位于可表示的值范围内时才需要这样做一个int
。char
可以是有符号的,也可以是无符号的。如果未签名,则测试为真;如果已签名,则c
和c >>> 4
将具有实现定义的值,因此它可能不正确。c
将具有实现定义的值,因此测试可能不正确。请注意,除了
memcpy()
问题之外,您的所有问题仅与值有关,而不与表示有关。I will make the added assumption that no types have padding bits on the implementation under discussion. Let's take them one at a time:
Yes.
No. Conversion of an out-of-range number to a signed type gives an implementation-defined result.
No, same reason as the previous example.
Yes. The standard guarantees that each value bit in a signed type has the same value in the object representation of the corresponding unsigned type.
Yes. The promotion of
i
fromint
tounsigned
is deterministic and produces the same value both in the assignment tou
and in the comparison.Yes, but only if
hex_literal
is in the range of (positive) values representable by anint
- otherwise the implementation-defined result strikes again.u == hex_literal
will always evalulate to true, buti == hex_literal
need only do so ifhex_literal
is in the range of values representable by anint
.char
may be signed or unsigned. If it is unsigned then the test will be true; if signed, thenc
andc >> 4
will have implementation-defined values, so it may not be true.c
will have an implementation-defined value, so the test may not be true.Note that all of your questions other than the
memcpy()
one pertain only to the values rather than the representation.对于未签名的,是的。对于有符号类型,没有;该标准允许 2 的补码、1 的补码或符号数值表示。标准(C99)的相关章节是6.2.6.2。
另一个问题是诸如
unsigned u = (int)0xffffffff
之类的代码会调用未定义的行为,因为这会导致整数溢出(第 6.3.1.3 节)。另一个问题是诸如
char c = 0xff; 之类的代码。 c>> 4
是实现定义的有两个原因。首先,char
可以是有符号
或无符号
。其次,如果它是有符号的,则右移负数是实现定义的(第 6.5.7 节)。For unsigned, yes. For signed types, no; the standard permits 2's complement, 1's complement or sign-magnitude representations. The relevant section of the standard (C99) is 6.2.6.2.
A separate issue is that code such as
unsigned u = (int)0xffffffff
invokes undefined behaviour, as this causes an integer overflow (section 6.3.1.3).Yet another issue is that code such as
char c = 0xff; c >> 4
is implementation-defined for two reasons. Firstly,char
can either besigned
orunsigned
. Secondly, if it'ssigned
, then right-shifting a negative number is implementation-defined (section 6.5.7).无符号数保证模 2^n 算术。对于签名的则没有这样的保证。
没有提及位模式。请注意,0xfffffff 不是“位模式”,它是一个数字(其“位模式”对于 C++ 标准没有意义),如果
x
是一个,则保证满足 x + 1 = 0您分配给 0xffffffff 的 32 位无符号数。Unsigned numbers have guaranteed modulo 2^n arithmetic. There is no such guarantee for signed ones.
Nothing is said about bit patterns. Note that 0xfffffff is not a "bit pattern", it is a number (whose "bit patterns" have no meaning for the C++ standard) which is guaranteed to satisfy x + 1 = 0 if
x
is an 32 bit unsigned number to which you assigned 0xffffffff.需要记住的关键一点是,十六进制文字(例如
0x0F
)指的是值(此处:15
),而不是位和的顺序。字节是物理存储的。它的存储方式取决于机器 - 有些会首先存储最低有效位,另一些则首先存储高位,据我所知,在 x86 上,它首先存储最低有效字节,但首先存储高位位第一的。
但
0x000F
等于15
始终是正确的。Key item to memorize is that hex literals (e.g.
0x0F
) refer to the value (here:15
), not the order in which bits and bytes are stored physically.It is machine dependant how this is stored - some will store the least significant bit first, others the high bit first, and AFAIK on x86 it's least significant byte first but high bit first.
But it is always true, that
0x000F
equals15
.