请看一下这两段伪汇编代码:
1)
li $t0,53
sll $t1,$t0,2
srl $t2,$t0,2
sra $t3,$t0,2
print $t1
print $t2
print $t3
Run Code Online (Sandbox Code Playgroud)
2)
li $t0,-53
sll $t1,$t0,2
srl $t2,$t0,2
sra $t3,$t0,2
print $t1
print $t2
print $t3
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,输出为:
212
13
13
后者是:
-212
107374...
-14
但不应该:sra (-53) = - (srl 53) ?
C++03 标准告诉我们,将按位移位运算符应用于有符号类型的结果可以是 UB 和 Impl。定义为负值。我的问题如下:为什么对于操作符<<它有未定义的行为,而对于操作符>>它只是实现定义的?是否有严格的原因导致结果<<也不能被实现定义?
提前致谢。
看看这个示例C代码(以一个测试用例为例):
main() {
unsigned long a, b;
int c;
c = 32;
a = 0xffffffff << 32;
b = 0xffffffff << c;
printf ("a=%x, b=%x\n", a, b);
}
Run Code Online (Sandbox Code Playgroud)
打印: a=0, b=ffffffff
我不明白为什么b不是零,就像一个.我在Microsoft C和GCC上测试了这个.
更新:我修复了愚蠢的错字(当然应该是<< c而不是<< b).但我的问题仍然存在,例如结果仍然相同.
我有一个vector<char>,我希望能够从向量中的一系列位获得无符号整数.例如

我似乎无法编写正确的操作来获得所需的输出.我想要的算法是这样的:
& 第一个字节用 (0xff >> unused bits in byte on the left)<< 结果留下了输出字节数*一个字节的位数| 这与最终输出<< 由每个字节的(字节宽度 - 索引)*位左边| 这个字节带有最终输出| 最终输出的最后一个字节(未移位)>> 最终输出由右边字节中未使用的位数这是我尝试编码它,但没有给出正确的结果:
#include <vector>
#include <iostream>
#include <cstdint>
#include <bitset>
template<class byte_type = char>
class BitValues {
private:
std::vector<byte_type> bytes;
public:
static const auto bits_per_byte = 8;
BitValues(std::vector<byte_type> bytes) : bytes(bytes) {
}
template<class return_type>
return_type get_bits(int start, int end) {
auto byte_start = (start - (start % bits_per_byte)) / bits_per_byte; …Run Code Online (Sandbox Code Playgroud) 我已经看到>>和>>>之前.有什么区别,什么时候使用?
我偶然发现了一个问题,询问你是否曾经不得不在实际项目中使用位移.我在许多项目中都使用了相当广泛的位移,但是,我从来不必使用算术位移,即位移,其中左操作数可能是负的,符号位应该移位而不是零.例如,在Java中,您将使用运算>>符进行算术位移(同时>>>执行逻辑移位).在经过深思熟虑之后,我得出的结论是,我从未使用>>过可能为负的左操作数.
正如本回答中所述,算术移位甚至是在C++中定义的实现,因此与Java相比 - 在C++中甚至没有用于执行算术移位的标准化运算符.答案还说明了一个有趣的问题,我甚至都没有意识到负面数字的变化:
+63 >> 1 = +31 (integral part of quotient E1/2E2)
00111111 >> 1 = 00011111
-63 >> 1 = -32
11000001 >> 1 = 11100000
Run Code Online (Sandbox Code Playgroud)
因此,当看到这些位时,-63>>1收益率-32是显而易见的,但也许不是大多数程序员一见钟情的预期.更令人惊讶的是(但在查看位时再次显而易见)-1>>1是-1,不是0.
那么,可能负值算术右移的具体用例是什么?
我正在尝试处理位板,这需要我在64位无符号整数中设置一个特定的位.要设置位i,我对所讨论的位板执行按位OR运算,左移数字.
#include <stdint.h>
uint64_t kings = 0ULL; // Also tried unsigned long long int before.
kings |= 1 << i;
Run Code Online (Sandbox Code Playgroud)
它从第0位到第31位工作正常,但不能用于第32位到第63位.我怀疑这是因为右侧的评估恰好是32位整数.因此,我尝试了一个临时变量.
uint64_t temp = 0ULL;
temp |= 1 << i;
Run Code Online (Sandbox Code Playgroud)
也许它仍然将右侧评估为32位整数,或者它是我无法弄清楚的其他问题.要输出整数,我使用的是std :: bitset <64>.例如:
uint64_t kings = 0ULL;
kings |= 1 << 3;
kings |= 1 << 59;
Run Code Online (Sandbox Code Playgroud)
预期小数值:576460752303423496
实际:8
std::bitset<64> x(kings);
std::cout << x;
Run Code Online (Sandbox Code Playgroud)
位值:0000000000000000000000000000000000000000000000000000000000001000
显然,只有国王| = 1 << 3; 工作正常.
总之,第32到63位有什么问题,我该如何解决?
我正在研究一些按位运算符,我想提取数字的最后16位二进制数字并对它们进行操作.我基本上想要看到像0xFFFFFFFF这样的负数,然后提取LSB FFFF并将它们连接起来,0这样我最终得到一个零,所以它看起来像0x0000FFFF.我只关心较小的负数,所以LSB应该是我需要的所有信息.
这是我在C中的方法:
#include <stdio.h>
int main(){
int a = -1, c = 0;
short b = (short)a;
printf("a is %x\nb is %x",a,b);
c = (0 << 16) | b;
printf("\nc is %x\n", c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的思维过程是,我可以在我转换int a到一个较短,使得它看起来像FFFF,而不是FFFFFFFF我将有一个更好的时间.对我来说不幸的是,这只是打印出ffffffff变量
请看下面的代码片段,它基本上只是将 1 个字节向左移动 24 位。
uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFF << 24;
printf("after : %016llX \n", i);
// gives:
// before: FFFFFFFF00000000
// after : FFFFFFFEFF000000
Run Code Online (Sandbox Code Playgroud)
最重要的 32 位是FFFFFFFE(E在最后观看)。这并不像我预期的那样。我不明白为什么左移 1 个字节 24 位会触及位 #32(位 #31 应该是最后一个修改的)它把最后一个F( 1111) 变成了E( 1110) 。
为了使其正常工作,我使用了0xFF无符号 ( 0xFFU)。
uint64_t i = 0xFFFFFFFF00000000;
printf("before: %016llX \n", i);
i += 0xFFU << 24;
printf("after : %016llX \n", i); …Run Code Online (Sandbox Code Playgroud) 无论字节序如何,位移和其他操作的行为总是像大字节序一样。所以小的数字在右边,大的数字在左边。符号位也位于左侧。
我的问题是哪里明确说是这样的?我的C11草案副本甚至没有提到字节顺序,并且在按位部分有一些我不理解的数学表达式,所以我不确定这部分在哪里。