问题
For example:
unsigned int numA = 66; // or anything really
unsigned int numB = -numA;
unsigned int numC = numA & numB
I understand that the bitwise complement operator can be used to get the two's complement (in conjunction with a +1).
The reason I ask is because I stumbled upon this in some code for a chess engine. Chess engines do a lot of 'hacky' things to get absolute speed, especially in the move generation functions that are called millions of times per second. (It doesn't help that it was an example of magic bitboard move generation - the most optimized of them all). This chess engine code in particular only works correctly under gcc compilation (I suspect).
How do different compilers treat this? In particular, how does gcc handle this compared to the C++ compiler in VS Studio 2012 Express.
Thanks.
回答1:
The relevant quote from the Standard is actually this:
(§5.3.1/8) The operand of the unary - operator shall have arithmetic or unscoped enumeration type and the result is the negation of its operand. Integral promotion is performed on integral or enumeration operands. The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the promoted operand. The type of the result is the type of the promoted operand.
(This is from C++11; it used to be 5.3.1/7 in older versions.)
So -num will be evaluated as 2CHAR_BIT*sizeof(num) - num (‡). The result will be of the same type as the operand (after integer promotion), i.e. it will also be unsigned.
I just tested with GCC and it seems to perform the operation in precisely the way described by the Standard. I'll assume this is the case for Visual C++ as well; otherwise it's a bug.
(‡) This formula assumes that the relevant number of bits corresponds to the size (in bits) of the variable in memory. As Keith Thompson points out in the comment, this can't be true if there are padding bits (i.e. when not all bits participate in the representation of the numerical value, which is possible according to §3.9.1/1). On a system that uses more bits to store the value than are used to represent the numerical value, the formula will not be accurate. (I, personally, am not actually aware of any such system, though.)
回答2:
Here's what C++ standard says under section 4.7.2 (Integral conversions):
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
Hope this answers your question.
回答3:
You asked about both C and C++. Remember that they're two different languages. In this particular case, they have the same rules for operations on unsigned types, but they're expressed differently.
Quoting the latest draft of the current (2011) ISO C standard), section 6.2.5p9:
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
The description of the unary "-" operator merely says that the result is "the negative of its (promoted) operand"; it assumes that the reader has read 6.2.5 to figure out what the "negative" of an unsigned integer is.
In either language, the result of:
unsigned int numA = 66;
unsigned int numB = -numA;
is to store UINT_MAX - 66U + 1U in numB. (The U suffixes aren't really necessary, but I include them to emphasize that this is all defined in terms of unsigned values.)
回答4:
I was bitten by the typeof(-Unsigned) is Unsigned. The VS2012 compiler takes this to interesting levels of inscrutable behaviour:
unsigned x = 0xFFFFFFFE; int y = -x/2;
What is "y"?
I would have expected x/2 = 0x7FFFFFFF, then -(x/2) = 0x80000001, i.e. -2**31-1. Instead, the compiler generates (-x) = 0x00000002, (-x)/2 = 0x00000001.
I guess that for boundary values, it's all Deathstar 9000. Sigh.
来源:https://stackoverflow.com/questions/14065337/what-does-the-unary-operator-do-on-unsigned-data-types-in-c-c-and-on-diff