位移位编译器错误还是特殊情况?

发布于 2024-12-17 18:40:36 字数 805 浏览 4 评论 0 原文

以下代码输出 0,1,32,33。至少可以说这是违反直觉的。但是,如果我用类型注释常量“ONE”替换文字 1,则循环运行正常。

这是使用 gcc 4.6.2 和 -std=c++0x 的情况。

#include<iostream>
#include<cstdint>
using namespace std;
int main()
    {
    int64_t bitmask = 3;
    int64_t k;
    const int64_t ONE = 1;
    cout<<"bitmask = "<<bitmask<<endl;

    for(k=0; k<64; k++)
        {
        if(bitmask & (1<<k))
            {
            cout<<"k="<<k<<endl;
            }
        }

    return 0;
    } 

编辑 问题:正如 Ben 指出的那样,默认情况下 1 被视为 32 位宽。当它的合作数是 64 位时,为什么它没有提升到 64 位。

解决方案

编号<<不要求每一侧都具有相同的类型。毕竟,当可用的最大移位适合 char 时,为什么要将右侧设置为 int64_t 呢?仅当您处理算术运算符而不是所有运算符时才会发生提升。

复制自下面 Bill 的评论

The following code outputs 0,1,32,33. Which is counter intuitive to say the least. But if I replace the literal 1 with the type annonated constant "ONE", the loop runs fine.

This is with gcc 4.6.2 and -std=c++0x.

#include<iostream>
#include<cstdint>
using namespace std;
int main()
    {
    int64_t bitmask = 3;
    int64_t k;
    const int64_t ONE = 1;
    cout<<"bitmask = "<<bitmask<<endl;

    for(k=0; k<64; k++)
        {
        if(bitmask & (1<<k))
            {
            cout<<"k="<<k<<endl;
            }
        }

    return 0;
    } 

EDIT
Question: As Ben pointed out, 1 is seen to be 32 bit wide by default. Why is it not promoted to 64 bits when it's co-operand is 64 bits.

SOLUTION

No. << does not require that each side have the same type. After all, why make the right side an int64_t when the maximum shift available fits in a char? The promotion only occurs when you are dealing with arithmetic operators, not all operators.

Copied from Bill's comments below

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏の忆 2024-12-24 18:40:36

这是一个问题:(1<

1 是适合 int 的整数文字。

如果 int 在您的平台上少于 64 位,则当 k< 时,(1< 在循环结束时将出现未定义的行为/code> 很大。在您的情况下,编译器正在使用英特尔位移指令,并且未定义的行为是通过英特尔定义大于操作数大小的移位的方式产生的 - 高位被忽略。

您可能想要 (1LL<


标准所说的内容(第 5.8 节 expr.shift):

操作数应为整型或无作用域枚举类型,并执行整型提升。结果的类型是提升后的左操作数的类型。如果右操作数为负数,或者大于或等于提升的左操作数的位长度,则行为未定义。

这与“通常的算术转换是针对
算术或枚举类型的操作数。”,它存在于例如加法和减法运算符中。

这种语言在 C++03 和 C++11 之间没有改变。

This is a problem: (1<<k).

1 is a integral literal that fits in an int.

If int has fewer than 64 bits on your platform, then (1<<k) will have undefined behavior toward the end of the loop, when k is large. In your case, the compiler is using an Intel bitshift instruction, and the undefined behavior comes out the way Intel defines shifts larger than the operand size -- the high bits are ignored.

You probably want (1LL<<k)


What the standard says (section 5.8 expr.shift):

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

This in contrast to the wording "The usual arithmetic conversions are performed for
operands of arithmetic or enumeration type." which is present for e.g. addition and subtraction operators.

This language didn't change between C++03 and C++11.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文