C++ 一元运算符是什么-&引用;在C/C++;(在不同的编译器上)?

C++ 一元运算符是什么-&引用;在C/C++;(在不同的编译器上)?,c++,c,compiler-construction,unsigned,C++,C,Compiler Construction,Unsigned,例如: unsigned int numA = 66; // or anything really unsigned int numB = -numA; unsigned int numC = numA & numB 我知道按位补码运算符可用于获取两个的补码(与a+1结合使用) 我问这个问题的原因是因为我在国际象棋引擎的一些代码中偶然发现了这一点。国际象棋引擎做了很多“黑客”的事情来获得绝对速度,特别是在每秒调用数百万次的移动生成函数中。(这是魔幻比特板移动生成的一个例子——它们中优化

例如:

unsigned int numA = 66; // or anything really
unsigned int numB = -numA;
unsigned int numC = numA & numB
我知道按位补码运算符可用于获取两个的补码(与a+1结合使用)

我问这个问题的原因是因为我在国际象棋引擎的一些代码中偶然发现了这一点。国际象棋引擎做了很多“黑客”的事情来获得绝对速度,特别是在每秒调用数百万次的移动生成函数中。(这是魔幻比特板移动生成的一个例子——它们中优化程度最高的一个,这并没有帮助)。这个国际象棋引擎代码只在gcc编译下正确工作(我怀疑)

不同的编译器如何处理这个问题?特别是,GCC如何处理VS Studio 2012 Express中的C++编译器?< /P>

>

这里是C++标准在4.7.2(积分转换)下所说的:

如果目标类型为无符号,则结果值最小 与源整数全等的无符号整数(模2n,其中n 用于表示无符号类型的位数)。[注:在 二的补语表示法,这种转换是概念上的和逻辑上的 位模式没有变化(如果没有截断)。 -[完注]


希望这能回答您的问题。

标准中的相关引用实际上是:

(§5.3.1/8)一元运算符的操作数应具有算术或非范围枚举类型,且结果为其操作数的求反。对整数或枚举操作数执行整数提升。无符号量的负数是通过从2n中减去其值来计算的,其中n是提升操作数中的位数。结果的类型是提升的操作数的类型

(这来自C++11;在旧版本中,它曾经是5.3.1/7。)

因此
-num
将被计算为2CHAR_BIT*sizeof(num)-num(&ddagger;)。结果将与操作数的类型相同(整数提升后),即它也将是无符号的

我刚刚用GCC进行了测试,它似乎完全按照标准描述的方式执行操作。我也假设这也是Visual C++的例子;否则它就是一个bug



(&ddagger;)此公式假定相关位数对应于内存中变量的大小(以位为单位)。正如基思·汤普森(Keith Thompson)在评论中指出的那样,如果存在填充位(即并非所有位都参与数字值的表示,根据§3.9.1/1,这是可能的),则不可能是真的。在使用比用于表示数值的位更多的位来存储值的系统上,公式将不准确。(我个人并不知道任何这样的系统。)

< P>你问了C和C++两个问题。记住它们是两种不同的语言。在这种特殊情况下,它们对无符号类型的操作具有相同的规则,但表达方式不同

引用现行(2011)ISO C标准第6.2.5p9节:

涉及无符号操作数的计算永远不会溢出,因为 无法由结果无符号整数表示的结果 类型按比最大值大一的数的模减少 可由结果类型表示的值

一元“-”运算符的描述仅表示结果是“其(提升的)操作数的负数”;它假设读者已经阅读了6.2.5,以了解无符号整数的“负数”是什么

在任何一种语言中,结果如下:

unsigned int numA = 66;
unsigned int numB = -numA;
UINT_MAX-66U+1U
存储在
numB
中。(后缀
U
并不是真正必要的,但我加入它们是为了强调这都是根据无符号值定义的。)

我被类型of(-unsigned)咬了一口。VS2012编译器将这一点带到了令人感兴趣的难以理解的行为级别:

无符号x=0xFFFFFE; int y=-x/2

什么是“y”

我希望x/2=0x7FFFFFFF,然后-(x/2)=0x80000001,即-2**31-1。 相反,编译器生成(-x)=0x00000002,(-x)/2=0x00000001


我猜对于边界值,它都是死亡之星9000。唉。

位数”不包括任何填充位(大多数实现中没有填充位),因此包含
CHAR\u位的表达式(我无法在注释中重现)并不总是准确的。@KeithThompson是的,我真的很想知道这一点。该标准在3.9.1/1中明确指出,在除
char
以外的整数类型中,并非所有位都必须参与值表示。但在上面引用的部分中,它说
n
是位数(而不是参与值表示的位数)。显然,填充位不可能计数(否则就没有意义了),但标准中的措辞在这里并不十分精确。这并不能直接回答问题。OP的示例代码中没有转换(除了将
66
int
转换为
无符号int
)。一元“-”应用于
无符号
值,并生成
无符号
结果。(它确实解释了
unsigned int max=-1;
的含义,但这不是问题所在。)检查优先级表,一元
-
的优先级高于
/
,谢谢。但为时已晚,我做到了。当然,真正令人惊讶的是“-(unsigned)”属于unsigned类型。