C++ -1和~0之间有区别吗?
比较无符号值时,如本测试中所示:C++ -1和~0之间有区别吗?,c++,c,C++,C,比较无符号值时,如本测试中所示: if (pos == (size_t)-1) 这种比较在技术上是否不同于: if (pos == (size_t)~0) 我不习惯第二种变体。这就是为什么我要问这个问题。如果答案是肯定的,答案可能是相当直接的。< P> C++标准保证 SiZeSt是无符号类型,无符号类型遵循通常的模块算术规则(其中模值是类型的值表示的二进制数的两倍,参见3.9/4),因此,转换为大小的-1必须是该类型可以表示的最大值 值0是一个int,并且~0具有翻转零的int表示中的所有
if (pos == (size_t)-1)
这种比较在技术上是否不同于:
if (pos == (size_t)~0)
我不习惯第二种变体。这就是为什么我要问这个问题。如果答案是肯定的,答案可能是相当直接的。< P> C++标准保证<代码> SiZeSt是无符号类型,无符号类型遵循通常的模块算术规则(其中模值是类型的值表示的二进制数的两倍,参见3.9/4),因此,转换为
大小的-1
必须是该类型可以表示的最大值
值0
是一个int
,并且~0
具有翻转零的int
表示中的所有位。该结果的值取决于平台上的int
表示形式。然后将该值(感谢@Matt McNabb,它可能是陷阱表示)转换为size\u t
(这是根据模运算规则完成的)
总之,结果值比较是否相等是由实现定义的。(例如,如果int
用2的补码表示,则~0
的值是-1
,因此两者是相同的。),这是:
用于等同于:
if(pos == (size_t)-1)
假设机器使用负整数的表示形式。因此,如果您希望代码100%可移植,就不应该假设它是标准。因此,在您的示例中,技术上没有任何区别。因为很难找到一个不会优化像-1
和~0
这样的文本操作的编译器。以你为例,我得到的确切信息如下:
; ...
movq $-1, -16(%rbp)
movq $-1, -8(%rbp)
; ...
不要害怕那些-1
,assebmly是无类型的;)
更有趣的问题是,您的示例是否为:
#include <stddef.h>
int main() {
int var0 = 0;
int var1 = 1;
size_t a = (size_t) -var1;
size_t b = (size_t) ~var0;
return a ^ b;
}
查看英特尔手册:
NEG
-二的补码否定
将操作数(目标操作数)的值替换为其
二的补码。(此操作相当于
从0中减去操作数。)
非
-补码否定
执行按位NOT操作(每个1设置为0,每个0
在目标操作数和存储上设置为1)
目标操作数位置中的结果
从理论上讲,我的结论是,在某些异域平台和编译器上,代码可能会有所不同,但在其他情况下–不。如果不确定,请始终检查平台上的程序集列表。好的-1
转换为unsigned是因为我不认为我们可以说~0
b/c取决于底层表示(直截了当)答案是否定的(没有区别)@barakmanos:那么直截了当的意思是错误的?不是一个精确的副本,但与大小密切相关,t
总是无符号的。C11确实指定了-1如何转换为无符号的:6.3.1.3,第2段。值是UINT\u MAX
@ShafikYaghmour~0
是有符号的。~0==0
很可能是在一个补码系统上,一个然后,转换到大小\u t
的结果仍然是零。如果是~0ULL
,那可能是另一回事。我见过有人称赞+0!=-0的机器。我不知道这是否是标准。@KerrekSB你说“取决于int
在你的平台上的表示。”。出于兴趣,如果反转发生在cast之后,即~(size\t)0)
。这会消除对int
实现的依赖性吗?也就是说,(size\t)-1
和~(size\t)0)
将是等效的,会有更有力的保证吗?(我上一次评论中的打字修正)@尼尔:我相信是的,尽管我刚才没有把所有的部分都放在一起。~
运算符被定义为一个补数,无符号整数的值是其值表示的二进制值(这是我缺少的部分),因此零的补数是“所有的一”这是最大的可表示的值。我认为它可能是标准所要求的。从C++草案;第3.9节,第7段;“积分类型的表示应该使用纯二进制记数系统来定义值。[示例:本国际标准允许整数类型使用2的补码、1的补码和带符号的幅值表示法。-结束示例]”+1我发现这是一对有趣的问答。@Niall:很难看出它还有什么其他意义,特别是如果你将3.9.1/4、3.9.1/7和脚注52结合起来。基本上,无符号整数有N个值位,位的值以通常的方式决定整数的值。实际上,只有有符号整数才有意义为实现细节留点余地。(当然,整数不需要唯一表示;它们很可能有填充。)注意,在补码中,~0
可能是陷阱表示(负零)
#include <stddef.h>
int main() {
int var0 = 0;
int var1 = 1;
size_t a = (size_t) -var1;
size_t b = (size_t) ~var0;
return a ^ b;
}
movl $0, -24(%rbp) ; var0 = 0
movl $1, -20(%rbp) ; var1 = 1
movl -20(%rbp), %eax
negl %eax ; 2's complement negation
; ...
movl -24(%rbp), %eax
notl %eax ; 1's complement negation
; ...