对未定义的C++班次操作员行为和换行"pattern space"感到困惑
Confused by undefined C++ shift operator behavior and wrapping "pattern space"
我对在不确定的C 行为的文章的"转移运营商"部分中阅读的内容感到困惑。
在手臂架构上,换档操作员总是表现得好像在256位模式空间中发生,无论操作数的大小如何,即重复或"环绕",只有每256个位置。另一种思考方式是,模式移动了指定数量的位置模式256。然后,结果当然包含模式空间最不明显的位。
桌子特别奇怪:
Given a 32-bit integer with a value of 1:
+-----------------------------------+
| Shift left ARM x86 x64 |
+-----------------------------------+
| 32 0 1 1 |
| 48 0 32768 32768 |
| 64 0 1 1 |
+-----------------------------------+
这些价值是什么,为什么重要?
轮班运算符不包装。根据C 规范,如果将32位值移动32,结果始终为0。(编辑:我错了,我错了,请参阅答案!)那么这篇文章是什么?什么是未定义的行为?
当我在x86上运行此代码时,我得到0
:
printf("%d", 1 << 32);
据说此代码段说明了问题:
// C4293.cpp
// compile with: /c /W1
unsigned __int64 combine (unsigned lo, unsigned hi) {
return (hi << 32) | lo; // C4293
// try the following line instead
// return ( (unsigned __int64)hi << 32) | lo;
}
我希望返回的值为lo
,因为程序员移走了所有hi
位。警告很好,因为这可能是一个错误,但是我看不出任何未定义的行为...
如果使用x86或x64机器指令来移动该值,它们将掩盖移位量,仅使用较低的位来进行实际偏移。其他一些硬件可能不会。
这就是为什么它不确定。
在您使用文字1 << 32
的示例中,编译器可能会计算值,这就是为什么它是0
。尝试在Real X86硬件上进行操作,您将获得1
。
结果的类型是晋升的左操作数的类型。如果右操作数为负,或大于或等于晋升的左操作数的位中的长度,则行为是不确定的。
这是从C 11的§5.8/1。如果您的INT为32位,则无法移动32(右移或左移动,无论左操作数的签名)。
根据C 规范,如果移动32位的32位值,结果始终为0
不,这不是标准所说的。不确定的行为是将32位类型移动32或更多(5.8/1)
由于不确定的行为是在手臂上移动256位(没有257位或更高的类型),因此CPU完全有权包装。
相关文章:
- 使用一个考虑到std::map中键值的滚动或换行的键
- 如何防止clang格式在流运算符调用之间添加换行符<<
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- 在 Stream C++ 文本之前有一个额外的换行符
- 流:CSV 文件中的换行符
- 将缓冲区复制到剪贴板 [换行错误]
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- Clang-格式:在多行语句之后的换行符上打开大括号
- 如何正确转发/换行static_cast?
- 在输出流中插入换行符
- 防止控制台在通道字符(在 c++ 中)中输入空格(即空格、制表符和换行符)
- QProcess::readAllStandardOutput() 和换行符
- 如果有换行符,clang 格式不会附加大括号
- 创建一个简单的前向迭代器,该迭代器在循环缓冲区的"end"处自动换行
- C++在标点符号后将字符串换行
- 提取后返回换行符的C++istream.get()
- 如何在出现换行符之前将多个整数作为输入?
- 正则表达式 获取两个换行符之间的文本
- 包含换行符分隔的单词的文件和C++中这些单词的字符串向量的大小是否相同?
- 对未定义的C++班次操作员行为和换行"pattern space"感到困惑