我知道有>>
符号整数的行为可以依赖于实现(具体来说,当左操作数为负时).
怎么样的人:~
,>>
,&
,^
,|
?当他们的操作数有符号内建类型(整数short
,int
,long
,long long
),都将结果保证是相同的(中位含量),好像他们的类型是无符号的?
我看到下面的代码行这里的C.
int mask = ~0;
Run Code Online (Sandbox Code Playgroud)
我已经打印了mask
C和C++ 的值.它总是打印-1
.
所以我确实有一些问题:
~0
要为掩码变量赋值?~0
什么?-1
而不是~0
吗?在C99中,术语算术运算出现了16次,但我没有看到它的定义.
术语算术运算符仅在文本中出现两次(同样没有定义)但它确实出现在索引中:
算术运算符
添加剂,6.5.6,
G.5.2按位,6.5.10,6.5.11,6.5.12
递增和递减
,6.5.2.4,6.5.3.1乘法6.5.5,G.5.1
移位,6.5.7
一元,6.5. 3.3
然后我们将+
-
|
&
(二进制)++
--
*
(二进制)/
%
<<
>>
~
作为算术运算符,如果索引被认为是规范的!
也许我们应该将算术运算识别为算术运算符的使用.但F9.4.5表示该sqrt()
功能也是算术运算,详情请参考IEC 60559(又名IEEE754).因此,必须有算术运算,而不仅仅是算术运算符的使用.
这个问题是关于C标准需要什么,而不是主流编译器可以可靠地期望做什么.让我们关注C99,尽管有关C89/ANSI或C11如何分歧的输入也会受到欢迎.
第6.2.6.2节介绍了整数类型的"负0"的概念,它将0x8000...
在使用整数的符号和幅度表示的0xFFFF...
系统中,或者在使用一个补码表示的系统中.(该标准还允许此类系统将这些位模式用于陷阱值而不是负0;并且使用显性/更常见的二进制补码表示的系统没有负0.)
在该部分的进一步说,该标准说:
如果实现支持负零,则只能通过以下方式生成它们:
- 的
&
,|
,^
,~
,<<
,和>>
带参数的运算符产生这样的值- ...
未指定这些情况是否实际产生负零或正常零,以及当存储在对象中时负零是否变为正常零.
如果实现不支持负零的行为
&
,|
,^
,~
,<<
,和>>
运营商的参数会产生这样的价值是不确定的.
据我所知,标准没有进一步说明"产生这种价值的论据"的含义.但是,阅读本文的自然方式表明,任何类似于x | y
您期望结果的操作0x8000...
或0xFFFF...
实际上符合标准的操作都具有未定义的行为.
咦?真?那么根据标准,即使在二进制补码机上,~0
真的会导致不确定的行为吗?那疯狂.这不是预期的解释.
它们是否意味着:在使用符号和幅度或一个补码表示的系统上,并且没有负零,那么按位运算的行为将产生如果这些系统将为负零的位模式有一个未定义.在具有两个补码表示的系统上,此处的标准保持沉默?
如果你在标准中进一步展望(第6.5.7节),它会告诉我们:
uint32_t x = 1;
int32_t y = 1;
x << -1; /* is undefined, so is y << -1 */
x << 32; /* is …
Run Code Online (Sandbox Code Playgroud) 我最近一直在研究表示数字的一个补码系统,根据我的理解,数字0有两个变量.有一个负零(-0)和一个正零(+0).
我的问题是,在一个补码架构中,这个异常在C中究竟是如何处理的?C是否区分-0和+0,或者这两种形式都被视为零.
如果在测试零时,+ 0和-0都返回TRUE,那么我想知道如果我们输入-0作为输入,下面的示例代码将如何工作以计算整数中的设置位数.
int bitcount(int x)
{
int b;
for (b = 0; x != 0; b++)
x &= (x-1);
return b;
}
Run Code Online (Sandbox Code Playgroud)
由于-0,在一个补码中,其所有位都设置为1,-0应该返回由任何其他数字设置的最高位数; 但是,看起来这个代码会使循环测试条件失败x != 0
,甚至不会进入循环,从而产生不正确的结果.
在C语言中,在一个补码架构中,是否有可能使循环条件对正零敏感,如下所示:x != +0
另外,如果我从+0中减去1,我会得到-0或-1.换句话说,在一个补码架构中,+ 0 - 1 = -0?
总而言之,在本次讨论中不要偏离太远,我只是想知道C如何处理一个补码架构中数字0的特殊性.