C语言位运算精选题
一、易错题
1.1 运算符的优先级
在 C 语言中,sizeof
是操作符,优先级较高;<<
是左移运算符,属于关系运算符;^
是按位异或运算符;&=
是复合赋值运算符,赋值类运算符优先级最低。按优先级从高到低排序为:sizeof
→ <<
→ ^
→ &=
。
答案:B
记忆:单目运算符优先级大于双目运算符。 &既是单目(取地址符)也是双目(按位与)。
算数>位移>关系>位运算符(&^| && ||)>条件运算符>赋值>逗号🎈
1.2 两侧必须都是整数
分析各选项:
- A(
&&
):逻辑与运算符,操作数可为任意类型(非零即表示“真”),无类型限制。 - B(
&
):若为按位与运算符,其运算数必须是整型或字符型(字符型本质是整型存储),符合题意。 - C(
!
):逻辑非运算符,操作数可为任意类型,判断真假,无类型限制。 - D(
||
):逻辑或运算符,操作数同样可为任意类型,无类型限制。
答案选 B。
在 C 语言中,位运算(如 &
、|
、^
、~
、<<
、>>
)的操作数必须是 整型数据(包括字符型,因为字符型本质以整型形式存储)。这是因为位运算直接作用于二进制位,而浮点数的二进制存储格式(如符号位、指数位、尾数位)与整型不同,无法直接进行位运算。
1.3 八进制位运算
。
56
的二进制为00111000
,46
的二进制为00101110
。- 按位与运算
00111000 & 00101110 = 00101000
。 00101000
转十进制:(32 + 8 = 40);转八进制:分组为010 1000
,即50
。
应选项 C。
八进制转二进制有更直接的方法:1位八进制数对应3位二进制数。具体操作如下:
- 对八进制数的每一位,直接转换为对应的3位二进制数,不足3位时左侧补0。
- 例如八进制数
056
:5
转二进制为101
,6
转二进制为110
,直接拼接得101 110
(即二进制101110
)。
这种方法比“八进制→十进制→二进制”更高效,无需借助十进制过渡。
十六进制同理,1位十六进制数对应4位二进制数
做位运算,要转换成2进制来弄!
1.4负数的二进制
思路解析
-
写出
20
的 16 位二进制:
20
的 16 位二进制为0000 0000 0001 0100
(前导补 0 至 16 位)。 -
按位取反:
对0000 0000 0001 0100
按位取反,得到1111 1111 1110 1011
(这是补码形式,最高位为1
,表示负数)。 -
补码转原码:
- 减 1:
1111 1111 1110 1011 - 1 = 1111 1111 1110 1010
。 - 取反:对
1111 1111 1110 1010
取反(符号位不变,其余位取反),得到原码1000 0000 0001 0101
,对应十进制21
,结合符号位,最终结果为-21
。
- 减 1:
对应选项 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
:
-
-8的补码表示:
- 正数
8
的 8 位二进制为00001000
。 - 转换为负数补码:先取反得
11110111
,再加1
,最终-8
的 8 位补码为11111000
。
- 正数
-
右移 2 位操作:
- 对补码
11111000
执行右移 2 位(>>2
),因是有符号数,右移补符号位1
,结果为11111110
。
- 对补码
-
补码转十进制:
- 对
11111110
还原原码:- 减
1
:11111110 - 1 = 11111101
。 - 取反(符号位不变):
10000010
,对应十进制-2
。
- 减
- 对
对于 unsigned char b = 248
:
248
的二进制为11111000
,右移 2 位后为00111110
,对应十进制62
(无符号数右移补 0)。
最终程序运行结果为:-2,62
。
1.7 printf的注意
在 C 语言中,函数参数按 从右到左 的顺序计算:
- 最右侧的
a
先参与计算,此时a=16
。- 中间的
a=a>>2
:16
二进制为10000
,右移 2 位得100
(十进制4
),赋值后a=4
。- 最左侧的
a>>2
:此时a=4
,右移 2 位得1
。
最终输出结果为:
1,4,16
。
补充
像十六进制,八进制这些本身都是无符号,右移直接补0就可以
负数右移时补1: