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

0

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++
c
gcc
casting
g++
asked on Stack Overflow Jul 5, 2014 by nevanom • edited Apr 22, 2019 by phuclv

3 Answers

8

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

answered on Stack Overflow Jul 5, 2014 by phuclv • edited Jun 22, 2019 by phuclv
4

You can use C syntax (int)(f>>31), it will work for both as this C-syntax is C++-compliant.

0

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 ints 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 2n, 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 ints, -1u is defined to be 0xFFFFFFFFu. The cast to int is not just superfluous, it actually causes the code to be nonportable.

answered on Stack Overflow Jul 5, 2014 by T.C. • edited Aug 3, 2014 by T.C.

User contributions licensed under CC BY-SA 3.0