请选择 进入手机版 | 继续访问电脑版

[C 语言] C语言位运算符的具体 使用

  [复制链接]
查看289 | 回复51 | 2021-9-12 19:16:34 | 显示全部楼层 |阅读模式
目次

对于更多紧凑的数据,C 程序可以用独立的位或多个组合在一起的位来存储信息。文件访问答应 就是一个常见的应用案例。位运算符答应 对一个字节或更大的数据单位中独立的位做处理:可以扫除 、设定,或者倒置任何位或多个位。也可以将一个整数的位模式(bit pattern)向右或向左移动。

整数范例 的位模式由一队按位置从右到左编号的位构成 ,位置编号从 0 开始,这是最低有用 位(least significant bit)。比方 ,思量 字符值'*',它的 ASCII 编码为 42,相称 于二进制的 101010:
位模式 0 0 1 0 1 0 1 0
位位置 7 6 5 4 3 2 1 0

在本例中,值 101010 被表示成一个 8 位的字节内容,因此前面多两个 0。

布尔位运算符

表 1 中罗列 的运算符可以对操作数的每个位举行 布尔运算。这种二元运算符把两个不同操作数内雷同 位置的位关联起来。被设定的位(也就是值为 1 的位)被表明 为 true,被扫除 的位(也就是值为 0 的位)被表明 为 false。

除布尔运算符 AND、OR 和 NOT 以外,也有位异或运算符(exclusive-OR,XOR)。这些都在表 1 举行 了罗列 。

运算符 意义 示例 对于每个位位置的效果 (1=设定,0=扫除 )
    &     位 AND  x&y  假如 x 和 y 都为 1,则得到 1;假如 x 或 y 任何一个为 0,或都为0,则得到 0
    |     位 OR  x|y  假如 x 或 y 为 1,或都为 1,则得到 1;假如 x 和 y 都为 0,则得到 0
    ^     位 XOR  x^y  假如 x 或 y 的值不同,则得到 1;假如 两个值雷同 ,则得到 0
    ~     位 NOT(I的补码)  ~x  假如 x 为 0,则得到 1,假如 x 是 1,则得到 0

表1 布尔位运算符

位运算符的操作数必须是整数范例 ,并且依照 平常 算术转换(usualarithmetic conversion)。转换后获得的操作数通用范例 就是整个计算效果 的范例 。表 2 展示了这些运算符的效果 。

表达式(或声明) 位模式
int a=6; 0···00110
int b=11; 0···01011
a&b 0···00010
a|b 0···01111
a^b 0···01101
~a 1···11001

表2 位运算符的效果

可以将一个整数 a 的特定位扫除 ,做法是将整数 a 和另一个整数举行 位 AND 运算,此中 ,另一个整数在必要 扫除 的位为 0,其他位则为 1,并位 AND 运算,此中 ,另一个整数在必要 扫除 的位为 0,其他位则为 1,并将 AND 运算的效果 赋值给整数 a。

该另一个整数,即位 AND 运算的第二个操作数,被设定为 1 的位置(称为位掩码),这些位置颠末 位 AND 运算,不会改变第一个操作数对应位置的值。比方 ,一个整数与一个位掩码 0xFF 举行 位 AND 运算后,将保留最低位置的 8 个位,而会扫除 其他全部 位的值:

  1. a &= OxFF; // 相当于:a = a & OxFF;
复制代码

在该示例中,复合赋值运算符 &= 也会实行 & 运算。复合赋值运算符与其他二元位运算符具有类似 的实行 方式,这里不再赘述。

位运算符也可以用来天生 位掩码,以供以后的位运算使用 。比方 ,在位模式 0x20 中,只有位5被设定。因此表达式 ~0x20 会天生 一个只有位 5 没有被设定的位掩码:

  1. a &= ~0x20; // 清除a中的位5
复制代码

位掩码 ~0x20 比 0xFFFFFFDF 更受欢迎,由于 它的可移植性更好:效果 不会受到机器字大小的影响(同时也更方便人阅读)。

也可以使用 运算符 |(OR)和 ^(XOR)来设定或扫除 特定位,下面是一个示例:

  1. int mask = OxC;
  2. a |= mask; // 设定a的位2和位3
  3. a ^= mask; // 求反a的位2和位3
复制代码

第二个转换使用 雷同 的位掩码,它会将第一次转换的效果 再反转一次。换句话说,b^mask^mask 会得到原来 b 的值。这个操作可以用于交换两个整数的值,而不必要 使用 第三个临时 变量:

  1. a ^= b; // 等效于 a = a ^ b;
  2. b ^= a; // 将a原来的值赋值给b
  3. a ^= b; // 将b原来的值赋值给a
复制代码

本例中的前两个表达式等同于 b=b^(a^b)或 b=(a^b)^b。其效果 等同于 b=a,副作用是 a 的值也被修改了,其修改后的值为 a^b。在这时,第三个表达式具有如下副作用 a=(a^b)^a 或 a=b(使用 a 和 b 的原始值)。

移位运算符

移位运算符将左操作数的位模式移动数个位置,至于移动几个位置,由右操作数指定。它们如表 3 罗列 。

运算符 意义 示例 效果
<< 向左移位 x< x 的每个位向左移动 y 个位
>> 向右移位 x>>y x 的每个位向右移动 y 个位

表3 移位运算符

移位运算符的操作数必须是整数。在现实 移位操作之前,两个操作数都要举行 整数提拔 (promotion)。右边操作数不可以为负值,并且必须少于左边操作数在整数提拔 之后的位长。假如 不符合这些条件,程序运行效果 将无法确定。

移位运算效果 的范例 等于左操作数在整数提拔 后的范例 。下面示例的移位表达式具有 unsigned long 范例 。

  1. unsigned long n = 0xB, // 位模式: 0 ... 0 0 0 1 0 1 1
  2. result = 0;
  3. result = n << 2; // 0 ... 0 1 0 1 1 0 0
  4. result = n >> 2; // 0 ... 0 0 0 0 0 1 0
复制代码

在向左移位运算时,右边多出来的位用 0 来添补 。移动超出左边边界的位则直接扬弃 。向左移动 y 个位置,就等同于将左操作数乘以 2^{y}:假如 左操作数 x 是无符号范例 ,那么表达式 x<

在向右位移运算时,假如 左操作数是无符号范例 ,或者左操作数是带符号范例 但为非负值,则左边多出来的位用 0 来添补 。在这种环境 下,表达式 x>>y 的效果 等效于表达式 x/2^{y} 的值。假如 左操作数是负值,那么由编译器决定用于添补 至左边多出来的位的内容,大概 是 0,也大概 是符号位。

  1. // 函数setBit()
  2. // 设定掩码m中p位置的位。
  3. // 使用定义在limits.h中的CHAR_BIT,存储一个字节内的位的数目。
  4. // 返回值: 完成位设定的新掩码,其中p位置已设定好
  5. // 如果p不是有效的位置,则返回原始掩码。
  6. unsigned int setBit( unsigned int mask, unsigned int p )
  7. {
  8. if ( p >= CHAR_BIT * sizeof(int) )
  9. return mask;
  10. else
  11. return mask | (1<<p);
  12. }
复制代码

移位运算符的优先级比算术运算符的优先级更低,但相对于比较运算符以及其他的位操作运算符,具有更高的优先级。上例表达式 mask|(1<

到此这篇关于C语言位运算符的详细 使用 的文章就先容 到这了,更多干系 C语言位运算符内容请搜刮 脚本之家从前 的文章或继续欣赏 下面的干系 文章渴望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar 天下第一菜鸟俅 | 2021-9-19 09:14:23 | 显示全部楼层
顶!顶!顶!
回复

使用道具 举报

avatar 忆清静丫 | 2021-9-19 21:12:58 | 显示全部楼层
楼上的别说的那么悲观好吧!
回复

使用道具 举报

avatar Aim_yuan | 2021-9-20 11:21:03 | 显示全部楼层
记得吃药!
回复

使用道具 举报

avatar 风雨狼 | 2021-9-26 01:42:05 | 显示全部楼层
admin楼主的文笔不错!
回复

使用道具 举报

avatar 陌上人如玉__ | 2021-9-27 17:43:18 | 显示全部楼层
对牛弹琴的人越来越多了!
回复

使用道具 举报

avatar 没有昵称513 | 2021-9-28 06:07:39 | 显示全部楼层
终于看完了,很不错!
回复

使用道具 举报

avatar 天蝎孤星等 | 2021-9-30 06:35:50 | 显示全部楼层
坚持回帖!
回复

使用道具 举报

avatar 刘得福姊妹 | 2021-10-1 21:57:25 | 显示全部楼层
好无聊啊!
回复

使用道具 举报

avatar fdxhcwe148498 | 2021-10-2 17:19:30 | 显示全部楼层
admin楼主发几张靓照啊!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则