十六进制常量位移位期间的C++行为
C++ behaviour during hex constant bit shifting
为什么以下表达式求值为0xFFFFFFFFFF000000
,而不是0x00000000FF000000
?如何获取0x00000000FF000000
?
#include <iostream>
#include <stdint.h> // uint64_t
#include <iomanip> // std::setfill, std::setw
#define hexLOG(x) std::cout << std::showbase << std::internal << std::hex << std::uppercase << (x) << std::nouppercase << std::dec << std::endl;
int main ()
{
hexLOG(0xFFFFFFFFFFFFFFFF & (0xFF << (8 * 3)));
return 0;
}
更新:
我创建了以下示例,以便您可以看到这两种方法之间的区别:
#include <iostream>
#include <stdint.h> // uint64_t
#include <iomanip> // std::setfill, std::setw
#define hexLOG(x) std::cout << std::showbase << std::internal << std::hex << std::uppercase << (x) << std::nouppercase << std::dec << std::endl;
int main ()
{
uint64_t mask = 0xFF;
hexLOG(" mask:", (mask << 56));
hexLOG(" mask:", (0xFFu << 56));
hexLOG(" mask:", (0xFFull << 56));
return 0;
}
这里的原因是0xFF
是您平台上的32位signed int
,而0xFFFFFFFFFFFFFFFF
可能是64位signed long long
。执行&
操作时,移位后的0xFF
(此时将保持值0xFF000000
)将升级为64位signed long long
,此时会进行符号扩展,以保留0xFF000000
在平台上表示负数的事实。
通常,左移正signed
整数以使符号位受到影响是未定义的行为。您通常应该使用unsigned
类型进行位移位操作。您可以在十六进制文字的末尾添加u
后缀,使其成为无符号文字:0xFFu
。
这是一个已签名/未签名的问题。默认情况下,(从内存中)常量的类型为int。编辑:在评论的基础上,我更深入地研究了,当然,我错了。正如Jordan Melo、Slava和molbdnilo所指出的,这个问题不是数字的符号扩展的结果,而是整数推广的结果。
解决方案如下:
#include <iostream>
#define hexLOG(x) std::cout << std::showbase << std::internal << std::hex << std::uppercase << (x) << std::nouppercase << std::dec << std::endl;
int main (void)
{
unsigned int inputVar = 0xFF;
hexLOG(0xFFFFFFFFFFFFFFFF & (inputVar << (8 * 3)));
return 0;
}
下面是由生成的程序集上的签名关键字引起的差异:
有符号int
main:
push rbp
mov rbp, rsp
push rbx
sub rsp, 24
mov DWORD PTR [rbp-20], 255
mov eax, DWORD PTR [rbp-20]
sal eax, 24
movsx rbx, eax ; mov 32bit eax into 64 bit rbx with sign extension
无符号int
main:
push rbp
mov rbp, rsp
push rbx
sub rsp, 24
mov DWORD PTR [rbp-20], 255
mov eax, DWORD PTR [rbp-20]
sal eax, 24
mov ebx, eax ; mov 32 bit eax into 32 bit ebx
相关文章:
- 理解boost::asio-async_read在无需读取内容时的行为
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- arr[-1]在c++中的奇怪行为
- 继承期间显示未知行为的子类
- 如何在c++中使用引用实现类似python的行为
- G锁定铸造到基础上会释放模拟行为
- 在C++中对T*类型执行std::move的意外行为
- std::当在256字节边界上写入整数时,流的奇怪行为
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 奇怪的构造函数行为
- 重载运算符new[]的行为取决于析构函数
- 不同语言中相同代码的不同行为
- 处理除以零会导致<csignal>意外行为
- 试图理解类对象的行为
- c++11评估顺序(未定义的行为)
- 从结构寻址时,MMAP变量的行为很奇怪
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 读取文件时运行时的未知行为
- strncpy之后的char数组的错误行为
- 此增量后语句是否会导致未定义的行为?