【C语言位运算精选题】

在这里插入图片描述

一、易错题

1.1 运算符的优先级

在这里插入图片描述

在 C 语言中,sizeof 是操作符,优先级较高;<< 是左移运算符,属于关系运算符;^ 是按位异或运算符;&= 是复合赋值运算符,赋值类运算符优先级最低。按优先级从高到低排序为:sizeof<<^&=

答案:B
记忆:单目运算符优先级大于双目运算符。 &既是单目(取地址符)也是双目(按位与)。
算数>位移>关系>位运算符(&^| && ||)>条件运算符>赋值>逗号🎈

1.2 两侧必须都是整数

在这里插入图片描述

分析各选项:

  • A(&&:逻辑与运算符,操作数可为任意类型(非零即表示“真”),无类型限制。
  • B(&:若为按位与运算符,其运算数必须是整型或字符型(字符型本质是整型存储),符合题意。
  • C(!:逻辑非运算符,操作数可为任意类型,判断真假,无类型限制。
  • D(||:逻辑或运算符,操作数同样可为任意类型,无类型限制。

答案选 B

在 C 语言中,位运算(如 &|^~<<>>)的操作数必须是 整型数据(包括字符型,因为字符型本质以整型形式存储)。这是因为位运算直接作用于二进制位,而浮点数的二进制存储格式(如符号位、指数位、尾数位)与整型不同,无法直接进行位运算。

1.3 八进制位运算

在这里插入图片描述
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/40c52e2ab7c44ccbb9665806f3fe5e0f.png

首先,056 是八进制数,转换为十进制是 (5 \times 8 + 6 = 46)。

  • 56 的二进制为 0011100046 的二进制为 00101110
  • 按位与运算 00111000 & 00101110 = 00101000
  • 00101000 转十进制:(32 + 8 = 40);转八进制:分组为 010 1000,即 50

应选项 C

八进制转二进制有更直接的方法:1位八进制数对应3位二进制数。具体操作如下:

  • 对八进制数的每一位,直接转换为对应的3位二进制数,不足3位时左侧补0。
  • 例如八进制数 056
    • 5 转二进制为 1016 转二进制为 110,直接拼接得 101 110(即二进制 101110)。

这种方法比“八进制→十进制→二进制”更高效,无需借助十进制过渡。

十六进制同理,1位十六进制数对应4位二进制数

做位运算,要转换成2进制来弄!

1.4负数的二进制

在这里插入图片描述

思路解析

  1. 写出 20 的 16 位二进制
    20 的 16 位二进制为 0000 0000 0001 0100(前导补 0 至 16 位)。

  2. 按位取反
    0000 0000 0001 0100 按位取反,得到 1111 1111 1110 1011(这是补码形式,最高位为 1,表示负数)。

  3. 补码转原码

    • 减 11111 1111 1110 1011 - 1 = 1111 1111 1110 1010
    • 取反:对 1111 1111 1110 1010 取反(符号位不变,其余位取反),得到原码 1000 0000 0001 0101,对应十进制 21,结合符号位,最终结果为 -21

对应选项 C

在计算机里的存储都是以补码的形式存放的,但是我们获取数据看的是原码,正数的原码和补码是一样的,负数的补码求原码-1再取反!!!

1.5 按位与结构体

在这里插入图片描述
在这里插入图片描述

答案:C


位域结构体详解(结合代码)

位域结构体(又称位段结构体)是 C 语言中用于精细控制内存分配的结构体,允许以二进制位为单位定义成员的存储长度,适用于底层协议解析、硬件寄存器操作等场景。以下结合代码分析:

1. 定义与成员
struct bit {  
    unsigned a_bit: 2;  // 占用 2 位二进制空间  
    unsigned b_bit: 2;  
    unsigned c_bit: 1;  
    unsigned d_bit: 1;  
    unsigned e_bit: 2;  
    unsigned word: 8;   // 占用 8 位二进制空间  
};  
  • 成员格式为 类型 成员名: 位数unsigned 表示无符号类型,确保二进制位仅用于数值存储。
  • 每个成员按指定位数占用内存,例如 a_bit 仅用 2 位,最多表示 (2^2-1=3)。
2. 存储分配规则
  • 从低位(二进制右侧)开始分配:输入数据转换为二进制后,从右至左按位域成员顺序填充。
  • 以代码为例:输入十六进制 96,转换为二进制 10010110(8 位)。按位域分配:
    • e_bit(2 位):取前2 位 10,值为 (2)。

1.6负数的补码

在这里插入图片描述

首先,int a = -1,在计算机中以补码形式存储,即二进制全 1

  • 0377 是八进制数,转换为二进制为 11111111(8 位)。
  • a | 0377 执行按位或运算,因 a 本身为全 1,结果仍为全 1

1 的补码表示十进制 -1,八进制(以 16 位为例)为 177777。最终输出:
-1,177777

负数补码求解,原码取反(符号位不变,1代表负)再+1

1.7负数的位移

在这里插入图片描述
对于 char a = -8

  1. -8的补码表示

    • 正数 8 的 8 位二进制为 00001000
    • 转换为负数补码:先取反得 11110111,再加 1,最终 -8 的 8 位补码为 11111000
  2. 右移 2 位操作

    • 对补码 11111000 执行右移 2 位(>>2),因是有符号数,右移补符号位 1,结果为 11111110
  3. 补码转十进制

    • 11111110 还原原码:
      • 111111110 - 1 = 11111101
      • 取反(符号位不变):10000010,对应十进制 -2

对于 unsigned char b = 248

  • 248 的二进制为 11111000,右移 2 位后为 00111110,对应十进制 62(无符号数右移补 0)。

最终程序运行结果为:-2,62

1.7 printf的注意

在这里插入图片描述
在这里插入图片描述

在 C 语言中,函数参数按 从右到左 的顺序计算:

  1. 最右侧的 a 先参与计算,此时 a=16
  2. 中间的 a=a>>216 二进制为 10000,右移 2 位得 100(十进制 4),赋值后 a=4
  3. 最左侧的 a>>2:此时 a=4,右移 2 位得 1

最终输出结果为:1,4,16

补充

在这里插入图片描述

像十六进制,八进制这些本身都是无符号,右移直接补0就可以

负数右移时补1:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱康代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值