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时,我必须再次进行所有这些讨论!(一个更随意的程序员有什么希望理解这里的复杂性呢)。我只对无符号类型执行位运算,以避免所有这些。

1
offset=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++!