为什么std::bitset以小端方式暴露位?

10

当我使用std::bitset<N>::bitset(unsigned long long)时,这会构造一个bitset对象,如果我通过operator[]访问它,位似乎以小端模式排序。例如:

std::bitset<4> b(3ULL);
std::cout << b[0] << b[1] << b[2] << b[3];

输出的结果是1100,而不是0011,也就是说最后一位(或 LSB)在较小的地址,即索引0处。

查阅标准后,它说:

将前M位位置初始化为val中相应的位值

程序员自然地想到二进制位从LSB到MSB(从右到左),因此前M位位置显然是LSB→MSB,所以第0位的位数是b[0]

然而,在进行移位操作时,定义如下:

E1 << E2的值是将E1向左移动E2位;空出的位将填充零。

在这里,必须将E1中的位解释为从MSB→LSB,并将其向左移动E2次。如果按照LSB→MSB编写,那么只有向右移动E2次才能得到相同的结果。

我很惊讶在C++的其他地方,该语言似乎呈现了自然的(英语;从左到右)书写顺序(在进行位运算(如移位等)时)。为什么这里要与众不同呢?


3
b[0]打印的是最低有效位(LSB)。我不明白你是如何从这个中得出“小端序”的。当你将其作为字符串打印时,输出为最高有效位(MSB)--> 最低有效位(LSB)。 - Prismatic
@Pris little-endian 意味着最后一位数字在小地址(低索引,0),阿拉伯数字系统是大端的,即最后一位(LSB)在较高的地址(索引从左到右)因此它很大,在这里则相反,变成了小端。如果你不确定字节序,请阅读此文 - legends2k
2
位集合的索引与字节序的任何考虑都不同。索引零是最低有效位(LSB)。字节序与此无关。 - Prismatic
请理解,我使用“小端”这个词只是为了给这种排序命名,我非常清楚标准没有大小端的概念。从阅读问题可以看出,我问的只是为什么实现会将标准中的引用解释为小端,而不是大端? - legends2k
2个回答

18

就标准而言,不存在字节序的概念。对于 std::bitset[template.bitset]/3 定义了位位置

在类 bitset<N> 对象和某种整数类型值之间进行转换时,位位置 pos 对应于位值 1<<pos。两个或多个位对应的整数值是它们的位值之和。

根据您的标准引用使用这个位位置定义:

将前 M位位置初始化为 val 中相应的位值

如果二进制表示中的 val11,则生成一个 bitset<N> b,其中 b[0] = 1b[1] = 1,其余位设为 0


1
正是我想要的,谢谢!我的困惑源于对位移运算符的定义的思考:E1 << E2 的值是将 E1 左移 E2 位置;空出的位填充为零。_ 为了理解它,应该将 E1 想象成(MSB->LSB)大端序(否则它意味着右移以获得相同的效果)。我认为标准在这里暗示了大端序,而在 bitset 中似乎采用了小端序。然而,标准随后澄清道:_结果的值为 E1 × 2^E2,对结果类型中可表示的最大值再加一取模。 - legends2k

10
这与比特通常的编号方式一致-比特0代表20,比特1代表21等等。这与架构的字节顺序无关,字节顺序涉及的是字节而不是位的排序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接