问题
C99 (ISO/IEC 9899:1999)
6.2.6.2/1 Integer types
The values of any padding bits are unspecified.45) A valid (non-trap) object representation of a signed integer type where the sign bit is zero is a valid object representation of the corresponding unsigned type, and shall represent the same value.
For any integer type, the object representation where all the bits are zero shall be a representation of the value zero in that type.
In the C99 standard, an integer type where all the bits are zero is guaranteed to represent the value 0
in that respective type. However, does this guarantee that the underlying binary value is what we expect it to be?
For example:
unsigned x = 42;
We'd normally expect a machine to store this decimal 42
value in memory as the binary 101010
value.
However, could some eccentric machine architecture store the same decimal 42
value as the binary 011011
value (not necessarily for a practical reason but simply because it can)?
If so, consider the following code utilizing a right shift operation:
unsigned y = x>>1; /* 101010>>1 or 011011>>1 */
Would y
hold the decimal value 21
(10101
in binary), or the decimal value 13
(01101
in binary)?
Does the C99 standard make any guarantee about the decimal representation of an unsigned integer type after a bitwise operation -- e.g. is a right shift guaranteed to be equivalent to an integer division by 2
on all machine architectures?
回答1:
The representation of the integer isn't specified in the standard.
However, the behavior of >>
and <<
is defined according to the meaning of bits, not their position.
So >> 1
moves the bit representing 4 to the bit representing 2, regardless of where these bits actually are.
Quoting the C99 standard section 6.5.7:
The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
回答2:
The >>
operator will move bits around. Under a normal system, that means just shifting them. But in reality, we're taking the bit that represents position 2^3
, and moving it to position 2^2
, no matter where it is.
So on all systems, assert(42 >> 1 == 21)
.
As to your second question, yes, as long as you ignore trap / padding bits. Those can obviously be different, but are also generally invisible to you.
回答3:
The standard does not guarantee anything about how things are physically stored in memory. There's no need for that. The machine can be ternary, decimal or analog at physical level, not binary. The machine is not even required to have physical bits.
All it guarantees about unsigned int is that the bitwise operators affect "bits" as elements of binary positional representation of the number. These are actually virtual bits. They can directly correspond to physical bits (as is typically the case in practice) or they can be purely conceptual.
The >>
operator is guaranteed to shift those virtual bits to the right, meaning that it is always guaranteed to divide a positive integral value by 2. So, for the initial value of x = 42
this x = x >> 1
is guaranteed to produce 21
in x
. That means that if some machine physically represented 42
as 011011
, the compiler for that machine would be required to generate code that would change that representation of 42
to the representation of 21
(whatever it is), even if physically the latter did not look like "right shifted" 011011
pattern.
来源:https://stackoverflow.com/questions/17045231/does-the-c99-standard-guaranteed-the-binary-representation-of-unsigned-int