位运算、大小端和位移操作,三者之间有何关联?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1264个文字,预计阅读时间需要6分钟。
一文高清字序程序和bit序+大小端的概念大家都很熟悉。这个概念主要针对32bit或64bit机器,多个字节的排序+输出顺序。这个词组非常奇特,了解了输出顺序。The Computer Science term Big-End
一文高清字节序和bit 序大小端的概念大家都很熟悉了。
这个概念主要是针对 32bit或者 64bit机器中,多个字节的排列顺序
出处这个词很奇怪,查了下出处。
The Computer Science terms Big-Endian and Little-Endian were introduced by Danny Cohen2in 1980. The key termendianhas its roots in the novel Gulliver’s Travels3by Jonathan Swift4where within a war occurs between two factions who are fighting over which end of a boiled egg should be opened for eating. The big end or the little end. Unsurprisingly, the same said book was the inspiration for the naming of theGulliverlibrary.
可以看到原出处是一个小说,里面描述两股势力因为 吃水煮蛋应该从鸡蛋的哪一端开始吃而发生了战争。类似于咸甜豆腐脑的争端。
Endianness就是指鸡蛋的两头。作者起这个名字,我猜是想代表字节序本质上是一个没有什么实质意义,却又真实存在的分歧。
具体区别一图流:
个人觉得小端相对来说比较符合直觉:
高位在高地址,低位在低地址。
引发的问题主要是在32位(或者64位)的机器上,如何解释 2字节或者单字节的数据。
以及一些强制类型转换可能出现的问题
bitwise endianness bit内部的大小端上面讨论的是,64位机器内部,8个字节的顺序问题
实际上,对于一个字节内部的Bit,也存在一个对称的问题,bit的排列顺序是怎么样的
给定一个结构体:
struct Byte { UINT8 bit0:1; UINT8 bit1:1; UINT8 bit2:1; UINT8 bit3:1; UINT8 bit4:1; UINT8 bit5:1; UINT8 bit6:1; UINT8 bit7:1; };
问题来了, bit 0 到底是在 Byte的 LSB还是在MSB?换个问的方法,我要修改bit 0, 是 byte |= (1 << 0), 还是byte |= (1 << 7)
简而言之的结论:不确定。
C99 §6.7.2.1, paragraph 10 says:
"The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined."
C99标准表示: 具体的bit order和compiler的实现相关。
所以用bit 来表示数据的方式,兼容性需要提个醒。
最安全的方式使用结构体内的成员引用方式。
如果需要显式的表示这些位置,最好用下面的定义方式:
1 /* Each of these preprocessor directives defines a single bit, 2 corresponding to one button on the controller. 3 Button order matches that of the Nintendo Entertainment System. */ 4 #define KEY_RIGHT 0b00000001 5 #define KEY_LEFT 0b00000010 6 #define KEY_DOWN 0b00000100 7 #define KEY_UP 0b00001000 8 #define KEY_START 0b00010000 9 #define KEY_SELECT 0b00100000 10 #define KEY_B 0b01000000 11 #define KEY_A 0b10000000 12 13 int gameControllerStatus = 0; 14 15 /* Sets the gameControllerStatus using OR */ 16 void KeyPressed( int key ) { gameControllerStatus |= key; } 17 18 /* Clears the gameControllerStatus using AND and ~ (binary NOT)*/ 19 void KeyReleased( int key ) { gameControllerStatus &= ~key; } 20 21 /* Tests whether a bit is set using AND */ 22 int IsPressed( int key ) { return gameControllerStatus & key; }
关于位运算 bitwise operation用了很多年C,关于左移和右移操作,经常还是搞不清楚到底操作符在哪边。
这里一次搞明白
C99的定义:
shift-expression:
additive-expression
shift-expression<<additive-expression
shift-expression>>additive-expression
<< 或者 >>的 右侧是具体移动的位数,左边则是被操作数
x = y >> 2; // y 向右移动2位 x = y << 2; // y 向左移动2位 logical shift & arithmic shift 逻辑位移和算数位移
当位移操作和有符号数搞在一起的时候,就需要非常小心。
单纯的shift我们称作logic shift
If the variable
chcontains the bit pattern11100101, thench >> 1will produce the result01110010, andch >> 2will produce00111001.
上面的ch,如果以无符号数来表示,则逻辑位移不会影响语义的表达。
但是如果以有符号数表示,则从一个负数变成了一个正数。如果用作乘法操作就非常危险了。
对于C语言,左移和右移是有区别的:- 左移永远都是logical shift
A left shift is always a logical shift (the bits that are shifted off the end are discarded, including the sign bit).
- 右移,在unsigned时是logical shift,在signed时候是arithmic shift : 即会复制之前的符号位到最高位。
For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.
本文共计1264个文字,预计阅读时间需要6分钟。
一文高清字序程序和bit序+大小端的概念大家都很熟悉。这个概念主要针对32bit或64bit机器,多个字节的排序+输出顺序。这个词组非常奇特,了解了输出顺序。The Computer Science term Big-End
一文高清字节序和bit 序大小端的概念大家都很熟悉了。
这个概念主要是针对 32bit或者 64bit机器中,多个字节的排列顺序
出处这个词很奇怪,查了下出处。
The Computer Science terms Big-Endian and Little-Endian were introduced by Danny Cohen2in 1980. The key termendianhas its roots in the novel Gulliver’s Travels3by Jonathan Swift4where within a war occurs between two factions who are fighting over which end of a boiled egg should be opened for eating. The big end or the little end. Unsurprisingly, the same said book was the inspiration for the naming of theGulliverlibrary.
可以看到原出处是一个小说,里面描述两股势力因为 吃水煮蛋应该从鸡蛋的哪一端开始吃而发生了战争。类似于咸甜豆腐脑的争端。
Endianness就是指鸡蛋的两头。作者起这个名字,我猜是想代表字节序本质上是一个没有什么实质意义,却又真实存在的分歧。
具体区别一图流:
个人觉得小端相对来说比较符合直觉:
高位在高地址,低位在低地址。
引发的问题主要是在32位(或者64位)的机器上,如何解释 2字节或者单字节的数据。
以及一些强制类型转换可能出现的问题
bitwise endianness bit内部的大小端上面讨论的是,64位机器内部,8个字节的顺序问题
实际上,对于一个字节内部的Bit,也存在一个对称的问题,bit的排列顺序是怎么样的
给定一个结构体:
struct Byte { UINT8 bit0:1; UINT8 bit1:1; UINT8 bit2:1; UINT8 bit3:1; UINT8 bit4:1; UINT8 bit5:1; UINT8 bit6:1; UINT8 bit7:1; };
问题来了, bit 0 到底是在 Byte的 LSB还是在MSB?换个问的方法,我要修改bit 0, 是 byte |= (1 << 0), 还是byte |= (1 << 7)
简而言之的结论:不确定。
C99 §6.7.2.1, paragraph 10 says:
"The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined."
C99标准表示: 具体的bit order和compiler的实现相关。
所以用bit 来表示数据的方式,兼容性需要提个醒。
最安全的方式使用结构体内的成员引用方式。
如果需要显式的表示这些位置,最好用下面的定义方式:
1 /* Each of these preprocessor directives defines a single bit, 2 corresponding to one button on the controller. 3 Button order matches that of the Nintendo Entertainment System. */ 4 #define KEY_RIGHT 0b00000001 5 #define KEY_LEFT 0b00000010 6 #define KEY_DOWN 0b00000100 7 #define KEY_UP 0b00001000 8 #define KEY_START 0b00010000 9 #define KEY_SELECT 0b00100000 10 #define KEY_B 0b01000000 11 #define KEY_A 0b10000000 12 13 int gameControllerStatus = 0; 14 15 /* Sets the gameControllerStatus using OR */ 16 void KeyPressed( int key ) { gameControllerStatus |= key; } 17 18 /* Clears the gameControllerStatus using AND and ~ (binary NOT)*/ 19 void KeyReleased( int key ) { gameControllerStatus &= ~key; } 20 21 /* Tests whether a bit is set using AND */ 22 int IsPressed( int key ) { return gameControllerStatus & key; }
关于位运算 bitwise operation用了很多年C,关于左移和右移操作,经常还是搞不清楚到底操作符在哪边。
这里一次搞明白
C99的定义:
shift-expression:
additive-expression
shift-expression<<additive-expression
shift-expression>>additive-expression
<< 或者 >>的 右侧是具体移动的位数,左边则是被操作数
x = y >> 2; // y 向右移动2位 x = y << 2; // y 向左移动2位 logical shift & arithmic shift 逻辑位移和算数位移
当位移操作和有符号数搞在一起的时候,就需要非常小心。
单纯的shift我们称作logic shift
If the variable
chcontains the bit pattern11100101, thench >> 1will produce the result01110010, andch >> 2will produce00111001.
上面的ch,如果以无符号数来表示,则逻辑位移不会影响语义的表达。
但是如果以有符号数表示,则从一个负数变成了一个正数。如果用作乘法操作就非常危险了。
对于C语言,左移和右移是有区别的:- 左移永远都是logical shift
A left shift is always a logical shift (the bits that are shifted off the end are discarded, including the sign bit).
- 右移,在unsigned时是logical shift,在signed时候是arithmic shift : 即会复制之前的符号位到最高位。
For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.

