代码用g ++但不是gcc编译
下面的代码用g ++而不是gcc编译,我想知道为什么?
inline unsigned FloatFlip(unsigned f) { unsigned mask = -int(f >> 31) | 0x80000000; return f ^ mask; }
我假设在C ++中,int(f >> 31)是一个构造函数,但这让我想知道为什么它包含在代码中。是否有必要?
C不支持C ++“函数式”转换。 你需要这样写
unsigned mask = -(int)(f >> 31) | 0x80000000;
你可以使用C语法(int)(f>>31)
,因为这个C语法符合C ++,所以它都适用。
正如讨论的其他答案一样, int(f >> 31)
是一个C ++函数式转换,它与C-style (int) (f >> 31)
具有相同的含义(int) (f >> 31)
。
这个演员如何重要?
实际上,这段代码看起来似乎太聪明了。 f >> 31
仅保留f >> 31
的最高位,因此它为1
或0
。 然后代码将它转换为int
并对其执行一元否定,给出-1
或0
,最后按位OR的结果为0x80000000
,它设置最高位,然后将结果存储到mask
。 假设一个二进制补码系统, -1
的表示为0xFFFFFFFF
,因此如果设置了f
的最高位,则mask
将变为0xFFFFFFFF
,否则为0x80000000
。
然而,问题是int
不必使用二补码。 例如,如果系统是一个补码,则-1
的表示将是0xFFFFFFFE
,如果系统是符号幅度,则-1
将是0x80000001
,并且mask
将具有错误的值。
具有讽刺意味的是,对于无符号操作数的一元否定是明确定义的,以执行该代码的作者可能想做的事情,在标准的§5.3.1[expr.unary.op] / p8中:
一元运算符的操作数应具有算术或无范围的枚举类型,结果是其操作数的否定。 对整数或枚举操作数执行整体提升。 通过从2 n减去其值来计算无符号数量的负数,其中n是提升的操作数中的位数。 结果的类型是提升的操作数的类型。
换句话说,假设32位int
, -1u
定义为0xFFFFFFFFu
。 转换为int
不仅仅是多余的,它实际上导致代码不可移植。