位移位和赋值
Bit shifting and assignment
本文关键字:赋值 更新时间:2023-10-16
这简直要把我逼疯了。
int a = 0xffffffff;
int b = 32;
cout << (a << b) << "n";
cout << (0xffffffff << 32) << "n";
输出是
-1
0
为什么我没有得到
0
0
当您移动一个值的位数不小于其大小(例如,对于32位整数,32位或更多位)时,会发生未定义行为。您刚刚遇到了一个未定义行为的例子。
简短的回答是,由于您使用的是32位int
的实现,因此语言标准规定32位移位是未定义的行为。C标准(第6.5.7节)和c++标准(第5.8节)都规定
如果右操作数的值为负或大于等于提升后的左操作数的宽度,则未定义该行为。
但是如果你想知道为什么:
许多计算机都有一条可以移动寄存器中的值的指令,但是硬件只处理实际需要的移位值。例如,当移动一个32位字时,只需要5位来表示移位值0…因此,硬件可能会忽略高阶位,在*86机器上也是如此(8086除外)。因此,编译器实现可以直接使用该指令,而无需生成额外的代码来检查移位值是否太大,C标准的作者(其中许多代表编译器供应商)规定,移位量较大的结果是未定义的。
你的第一次移位是在运行时执行的,它遇到了这种情况…你的机器只考虑b的低阶5位,它们是0,所以不会发生移位。第二次移位是在编译时完成的,编译器会以不同的方式计算值,并实际进行32位移位。
如果你想移动的量可能大于你要移动的东西的位数,你需要自己检查值的范围。一种可能的方法是
#define LEFT_SHIFT(a, b) ((b) >= CHAR_BIT * sizeof(a)? 0 : (a) << (b))
c++标准规定::如果右操作数的值为负或大于或等于提升后的左操作数的宽度,则未定义该行为。由于GCC没有选项来处理负的量或可预测的类型宽度之外的量或捕获它们;它们总是被视为未定义的。所以行为没有定义
相关文章:
- 为"adjacent"变量赋值时出现问题
- C++中的赋值发生,尽管右侧出现异常
- 用C++中的sscanf赋值
- 为std::string的某个索引赋值
- 重载Singly Linked List中的赋值运算符
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- gtest_使用setargpointee在函数中赋值
- 非常量变量只读位置的赋值
- 使用赋值运算符重载从类中返回jobject
- C++数据文件、数组和计算赋值
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 全局作用域中函数指针的赋值
- 错误:在为指针赋值时,void值没有被忽略
- 标准库类型的赋值运算符的引用限定符
- 关于 c++ 函数中指针赋值的简单问题
- 复制构造函数、赋值运算符C++
- 标准::变体的赋值运算符
- cin >> int 给定一个字符串将 int 赋值为 0
- if 子句中的赋值不起作用
- 复制包含C++所有元素的对象!(构造函数和赋值,最佳实践?