C 换档计数为负数的左换档

C 换档计数为负数的左换档,c,C,这里到底发生了什么 a该行为未定义 在5位二进制算术中,2的补码-5具有与无符号+27相同的二进制表示形式,这可能解释了特定的平台。右侧的负整数在C语言中是未定义的行为 ISO 9899:2011 6.5.7位移位运算符: 对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负或大于或等于提升后的左操作数的宽度,则行为未定义 如果要移位的值是32位变量,则移位-5进入循环并向前移位27。移位只能以无符号方式进行。正如其他成员已经回答的那样,它会产生未定义的行为。我想在这

这里到底发生了什么


a该行为未定义


在5位二进制算术中,2的补码-5具有与无符号+27相同的二进制表示形式,这可能解释了特定的平台。

右侧的负整数在C语言中是未定义的行为

ISO 9899:2011 6.5.7位移位运算符:

对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负或大于或等于提升后的左操作数的宽度,则行为未定义


如果要移位的值是32位变量,则移位-5进入循环并向前移位27。移位只能以无符号方式进行。

正如其他成员已经回答的那样,它会产生未定义的行为。我想在这里提到的是,你引用的《一台机器上的书》似乎有点偏颇。它不能概括这种行为。这本书可能还解释了,按照标准,行为是未定义的。 顺便说一句,我刚刚浏览了新的C标准——一篇经济和文化评论,发现了这样一句话:

英特尔奔腾SAL指令 由gcc和Microsoft共同生成 只评估左移使用的C++ 移位的最后五位 数量

这很好地解释了为什么-5的左移会导致2的负数补码表示的27的左移

int main()
{
    unsigned int a = 1;
    printf("%u\n",a<<(-1));
    return 0;
}
输出为2147483648

这是我的假设和验证:只是假设


如果你的书没有提到这是未定义的行为,你应该考虑再读一本书。根据书中所说的其他内容,你可以认为这正是它所说的,尽管它可以说得更清楚。在一台机器上,某件事隐式地发生意味着它可能不会发生在其他机器上。如果这不起作用,是否是某个操作会具有与问题中所需行为相同的行为?为这个特殊的操作写一个等式似乎有点悲哀:。我尝试做一个右移,使1变成0。这里定义的未定义而不是实现的基本原理是什么?例如,某些主要架构是否会引发异常?@CiroSantilli六四事件法轮功 许多未定义的行为来自于C标准委员会的缺点,而不是关于硬件限制的合理理由。但在这种情况下,我看不出有多少改进的余地:如果标准强制将正确的操作数升级为无符号类型,最终仍然会得到类似于a的结果,但是如果32位变量是有符号的,整数升级将不会改变-5的有符号性。然后行为是未定义的,程序可以自由地停止并着火。无论如何,我认为这是一个糟糕的做法:我确信OP书中的“一机一句”只是一个例子,在声明这是未定义的之后。这实际上是一个很好的例子,未定义真的意味着什么,而不仅仅是执行程序的突然终止。如果以这种方式使用,就没有必要给人留下这样的印象,即27次左移是你有权利期待的。回答问题的这一部分+1,当以负移位计数移位时,(在引用的一台机器上)到底发生了什么。当然,UB就是UB,所以我们不应该对此作任何假设,但这个解释非常能说明导致他们做出UB的危险。我的大脑总是想说‘但是为什么不能用字面上的整数来定义呢’,但后来我想得更多,意识到这是荒谬的-5位二进制算法是真的吗?char是如何定义的?@ClsForCookies-在电气层面上,它是真实的。8.8对于2的幂来说没有什么特别的。注意,这个行为实际上是未定义的行为,你不能依赖它以模32运算。未定义的行为是未定义的