C++ ~3可以安全地自动加宽吗?
在回答时,我试图证明将操作数强制转换为C++ ~3可以安全地自动加宽吗?,c++,casting,bit-manipulation,C++,Casting,Bit Manipulation,在回答时,我试图证明将操作数强制转换为~运算符是正确的,但我无法想出一个不强制转换操作数将产生错误结果的场景 我提出这一澄清问题是为了能够澄清另一个问题,消除一些杂念,只保留最相关的信息 问题是我们想清除变量的两个最低位: offset = offset & ~3; 这看起来很危险,因为无论偏移量是多少,~3都将是int,因此我们可能会屏蔽不适合int宽度的位。例如,如果int是32位宽,而offset是64位宽的类型,可以想象此操作将丢失offset的32个最高有效位 然而,在实践中
~
运算符是正确的,但我无法想出一个不强制转换操作数将产生错误结果的场景
我提出这一澄清问题是为了能够澄清另一个问题,消除一些杂念,只保留最相关的信息
问题是我们想清除变量的两个最低位:
offset = offset & ~3;
这看起来很危险,因为无论偏移量是多少,~3
都将是int
,因此我们可能会屏蔽不适合int
宽度的位。例如,如果int
是32位宽,而offset
是64位宽的类型,可以想象此操作将丢失offset
的32个最高有效位
然而,在实践中,这种危险似乎并没有表现出来。相反,~3
的结果被符号扩展以填充偏移量
的宽度,即使偏移量
是无符号的
这种行为是标准规定的吗?我这样问是因为这种行为可能依赖于具体的实现和/或硬件细节,但我希望能够根据语言标准推荐正确的代码
如果我尝试移除32,我可以使操作产生不希望的结果。最低有效位。这是因为~(1的结果在符号大小表示法中无效。在32位整数的表示法中,~3
是-0x7FFFFFFC
。当它扩展到64位(有符号)时值被保留,-0x7FFFFFFC
。因此,我们不会说符号扩展发生在该系统中;您将错误地屏蔽所有32位及更高的位
在2的补码中,我认为偏移量&=~3
总是有效的。~3
是-4
,因此无论64位类型是否有符号,您仍然会得到一个只有底部2位未设置的掩码
offset = offset & ~(1 << 31); // BZZT! Fragile!
然而,就我个人而言,我会尽量避免写它,因为在以后检查我的代码是否有bug时,我必须再次进行所有这些讨论!(一个更随意的程序员有什么希望理解这里的复杂性呢)。我只对无符号类型执行位运算,以避免所有这些。1offset=offset&~3
如果我们使用符号大小,则是错误的,但是我认为这些都是相当学术性的问题;也许可以更新您的问题,以清楚地说明您是否要假设两个值complement@MattMcNabb但是1u是,1u进一步信息: 3?<代码>或者仅仅是表达式<代码> 3 <代码>?它允许符号大小、补码和两个补码。我不知道任何不使用两个补码的现代系统。(或任何支持C++的系统,就这点而言)offset&~3
是offset&(~3)
,因此~3
是int
,然后将int
转换为offset
的类型,以便执行&
选项1,如果您知道使用的是哪种符号表示,那么它是定义良好的(如果不是的话,我想你会说它是实现定义的,因为使用的是I-d符号表示)。将更新我的答案,以解决2的补码
offset = offset & ~static_cast<decltype(offset)>(1 << 31); // BZZT! Fragile!
offset = offset &
~static_cast<decltype(offset)>(
static_cast<unsigned int>(
1 << 31
)
);
// Now it finally looks like C++!