简体   繁体   中英

Why does this code compile with g++ but not gcc?

The following piece of code compiles with g++ and not gcc, and am stuck wondering why?

inline unsigned FloatFlip(unsigned f)
{
    unsigned mask = -int(f >> 31) | 0x80000000;
    return f ^ mask;
}

I would assume that in C++,

int(f >> 31)

is a constructor but that leaves me wondering why it's included in the code. Is it necessary?

C doesn't support the C++ "function-style" casting . You need to write it like this

unsigned mask = -(int)(f >> 31) | 0x80000000;

See cast operator

您可以使用C语法(int)(f>>31) ,因为此C语法符合C ++,因此对这两种语法都适用。

As the other answers discussed, int(f >> 31) is a C++ function-style cast, and it has the same meaning as the C-style (int) (f >> 31) .

How is this cast important?

Actually, this code looks like it's trying to be too clever. f >> 31 retains only the highest-order bit in f , so it's either 1 or 0 . The code then casts it to an int and performs unary negation on it, giving you either -1 or 0 , and finally bitwise-OR's the result with 0x80000000 , which sets the highest bit and then stores the result into mask . Assuming a two's complement system, -1 's representation is 0xFFFFFFFF and so mask will become 0xFFFFFFFF if the highest-order bit of f is set, and 0x80000000 otherwise.

The problem, however, is that int s do not have to use two-complement. If the system is one's complement, for instance, -1 's representation would be 0xFFFFFFFE , and if the system is sign-magnitude, -1 would be 0x80000001 , and mask will have the wrong value.

The irony is that unary negation for unsigned operands is well-defined to do what the author of this code presumably wanted to do, in §5.3.1 [expr.unary.op]/p8 of the standard:

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 2 n , where n is the number of bits in the promoted operand. The type of the result is the type of the promoted operand.

In other words, assuming 32-bit int s, -1u is defined to be 0xFFFFFFFFu . The cast to int is not just superfluous, it actually causes the code to be nonportable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM