C ++ 14中的二进制文字的字节顺序是什么?
我已经尝试过四处search,但一直没能find关于二进制文字和字节序的内容。 二进制文字是小端,大端还是别的(比如匹配目标平台)?
举例来说, 0b0111
的十进制值是0b0111
? 是7吗? 平台特定? 别的东西? 编辑:我选了一个不好的值7,因为它是在一个字节内表示。 尽pipe如此,这个问题已经得到了充分的回答。
一些背景知识:基本上我想弄清楚最不重要的位是什么值,用二进制文字掩盖它似乎是一个很好的方法去…但只有当有一些关于endianness的保证。
简答: 没有一个 。
长的回答:Endianness不会直接暴露在代码中,除非你真的试图把它弄出来(比如使用指针技巧)。 0b0111
是7,与hex的写法是一样的
int i = 0xAA77;
在某些平台上并不意味着0x77AA
,因为这样做是荒谬的。 无论如何,多余的零点在哪里呢? 他们会在前面填充,然后整个东西翻转,或者他们会被添加后? 如果是这样的话,我不知道会有人期待什么。
关键在于C ++不会对机器的字节顺序做任何假设,如果您使用原语和其提供的字面值编写代码,则机器之间的行为将是相同的(除非您开始绕过types系统,你可能需要这样做)
为了解决您的更新问题:编号将是您写出来的方式。 这些位不会被重新sorting或任何这样的事情,最重要的位在左边,最不重要的位在右边。
这里似乎有一个关于什么是sorting的误解 。 字节顺序是指字节在内存中的sorting方式,以及它们是如何解释的。 如果我把“4172”这个数字给了你,并且说“如果这是一千七百二十四,这是什么东西?”你不能真的给出答案,因为这个问题是没有意义的。 ( 有些人可能会认为,左边最大的数字表示大端,但没有内存地址的问题是不能回答的 )。 这只是一个数字,没有字节解释,没有内存地址。 假设4字节的整数表示,对应的字节是:
low address ----> high address Big endian: 00 00 10 4c Little endian: 4c 10 00 00
所以,给予这些任何一个,并告诉“这是计算机的内部代表4172”,你可以确定是否它的小或大端。
所以现在考虑你的二进制文字0b0111
这4位代表一个nybble,并可以存储为
low ---> high Big endian: 00 00 00 07 Little endian: 07 00 00 00
但是你不必关心,因为这也是由硬件来处理的,语言规定编译器从左到右读,最重要的是从最低位到最低位
字节顺序不是关于个别位 。 假设一个字节是8位的,如果我给你0b00000111
并且说“这个小的或者大的endian? 你再也不能说因为你只有一个字节。 字节顺序不重新sorting字节中的位,指的是对整个字节进行重新sorting(当然除非有一位字节)。
你不必关心你的电脑在内部使用什么。 0b0111
只是节省了你写东西的时间
unsigned int mask = 7 // only keep the lowest 3 bits
通过写作
unsigned int mask = 0b0111;
无需评论解释数字的意义。
所有整数文字(包括二进制文字)的解释方式与我们通常读取的数字相同(最左边的数字是最重要的)。
C ++标准保证文字的相同解释,而不必关心你所处的特定环境。 因此,在这种情况下,您不必关心sorting问题。
你的例子0b0111
总是等于七。
关于数字文字,C ++标准不使用字节顺序的术语。 相反,它只是描述文字有一个一致的解释,而解释是你所期望的。
C ++标准 – 整型文字 – 2.14.2 – 第1段
整数字面量是一个没有周期或指数部分的数字序列,可选地分隔单引号,在确定其值时被忽略。 整数字面量可以有一个前缀,用来指定其基数和一个指定其types的后缀。 数字序列的词汇第一位是最重要的。 二进制整数字面量(基数2)以0b或0B开头,由二进制数字序列组成。 八进制整数字面量(基数八)以数字0开头,由一系列八进制数字组成。 十进制整数文字(十进制)以0以外的数字开头,由十进制数字组成。 hex整数字面值(hex)以0x或0X开始,由hex数字序列组成,hex数字包括十进制数字,字母a到f和从A到F的十进制数字十到十五。 [例如:十二号可写12,014,0XC或0b1100。 文字1048576,1'048'576,0X100000,0x10'0000和0'004'000'000都具有相同的值。 – 结束示例]
维基百科描述了什么是endianness,并以我们的数字系统为例来理解big-endian 。
术语endian和endianness指的是当这些字节被存储在计算机存储器中时用于解释构成数据字的字节的约定。
Big-endian系统在最小地址中存储一个字的最高有效字节,最低有效字节存储在最大地址中 (同时参见最高有效位)。 相反,小端系统将最低有效字节存储在最小地址中。
字节顺序上的一个例子就是考虑一个十进制数字是如何写入地址值的。 假设一个写入系统,其中数字是从左到右写的,最左边的位置类似于最小的内存地址,最右边的位置是最大的。 例如,一百二十三号写了1 2 3,最左边的是数百个地方。 任何人读这个数字也知道最左边的数字是最大的地方价值。 这是一个在日常生活中遵循的大尾巴惯例的例子。
在这种情况下,我们正在考虑一个整数字面的数字是“一个字的字节”,而这个字就是字面本身。 另外,文字中最左边的字符被认为是最小的地址。
字面1234
,数字1234
和4是“字的字节”, 1234
是“字”。 使用二进制文字0b0111
,数字零,一,一和一是“一个字的字节”,而字是0111
。
这种考虑使我们能够理解C ++语言环境下的字节顺序,并显示整数字面类似于“big-endian”。
您错过了源代码中的字节顺序和目标代码中所代表的字节顺序之间的区别。 每个人的答案都是毫不奇怪的:源代码文字是bigendian,因为这就是人类阅读它们的方式,而目标代码则是由目标代码读取的。
由于一个字节在定义上是最小的内存访问单位,所以我不认为有可能把一个字节的字节的内部表示赋予一个字节序列 – 唯一的办法是发现较大数字的字节序(无论是有意的还是有意的令人惊讶的是)通过从存储分段访问它们,并且该字节被定义为最小的可访问的存储单元。
C / C ++语言不关心多字节整数的字节顺序。 C / C ++编译器呢。 编译器parsing你的源代码并为特定的目标平台生成机器代码。 一般而言,编译器以存储整数的方式存储整数文字; 这样目标CPU的指令将直接支持在内存中读写。
编译器负责处理目标平台之间的差异,所以你不必这样做。
唯一需要考虑字节顺序的是当你与其他有不同字节顺序的系统共享二进制值的时候。然后你可以逐字节地读取二进制数据,并按照正确的顺序排列你的代码运行的系统。
一张照片有时超过千字。
在别处我会说即使编译器不在乎,例如在LLVM平台上只有后端(在技术上不是编译器)会考虑到endianess。
你可能想把C或者C ++或者任何其他语言看作本质上是小端的(想想按位运算符是如何工作的)。 如果底层硬件是大端,编译器可以确保数据以大端存储(对于其他端序),但是你的位操作就好像数据是小端的一样。 需要记住的是,就语言而言,数据是微不足道的。 将数据从一种types转换为另一种types时,会出现字节序相关的问题。 只要你不这样做,你是好的。
我被质疑了“C / C ++语言本质上是小端的”这样的陈述,因此我提供了一个很多知道它如何工作的例子,但是在这里我去了。
typedef union { struct { int a:1; int reserved:31; } bits; unsigned int value; } u; u test; test.bits.a = 1; test.bits.reserved = 0; printf("After bits assignment, test.value = 0x%08X\n", test.value); test.value = 0x00000001; printf("After value assignment, test.value = 0x%08X\n", test.value);
输出在一个小端系统上:
After bits assignment, test.value = 0x00000001 After value assignment, test.value = 0x00000001
大端系统上的输出:
After bits assignment, test.value = 0x80000000 After value assignment, test.value = 0x00000001
所以, 如果你不知道处理器的字节顺序 ,那么所有的东西都出来了吗? 在小端系统! 因此,我说C / C ++语言本质上是小端的。