Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the unary operator "-" do on unsigned data types in C/C++ (and on different compilers)?

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.

like image 507
Eric Thoma Avatar asked Dec 28 '12 06:12

Eric Thoma


People also ask

What is the purpose of the unary & operator in C?

These are the type of operators that act upon just a single operand for producing a new value. All the unary operators have equal precedence, and their associativity is from right to left. When we combine the unary operator with an operand, we get the unary expression.

What are unary operator used for?

Sizeof Unary Operator is used to return the size of the operand, in bytes. For example, in C++, the int data type is of the size 4 bytes. This value will be returned by the sizeof operator. The sizeof() operator is used as a function in the program.

What is unary operator in C with example?

The unary operator is used to change the sign of any positive value to a negative value. It means it changes the positive number to the negative, and a negative number becomes the positive number using the unary minus operator. Example 1: #include <stdio.

What is unsigned data type in C?

unsigned char is a character datatype where the variable consumes all the 8 bits of the memory and there is no sign bit (which is there in signed char). So it means that the range of unsigned char data type ranges from 0 to 255.


1 Answers

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 (&ddagger;). 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.


(&ddagger;) 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.)

like image 89
jogojapan Avatar answered Oct 14 '22 08:10

jogojapan