位运算与强制类型转换

变量基础

在C语言中,变量是程序中最基本的数据存储单元,用于存储各种类型的数据。

变量的声明与初始化

变量需要先声明后使用,声明格式:数据类型 变量名;

// 变量声明示例
int age;           // 声明整型变量
float salary;      // 声明浮点型变量
char grade;        // 声明字符型变量

// 变量初始化
int count = 0;     // 声明并初始化
double pi = 3.14;  // 声明并初始化

变量的命名规则

  • 只能包含字母、数字和下划线
  • 必须以字母或下划线开头
  • 不能使用C语言关键字
  • 区分大小写

练习题

1. 下列哪个是合法的变量名?

A. 2var
B. var-name
C. _var
D. int

答案:C. _var

解析:变量名不能以数字开头(A错误),不能包含连字符(B错误),不能使用关键字(D错误)。以下划线开头的变量名是合法的。

2. 关于变量声明,以下说法正确的是?

A. 变量可以不声明直接使用
B. 变量声明必须包含初始值
C. 变量声明指定了变量的数据类型
D. 变量名可以包含空格

答案:C. 变量声明指定了变量的数据类型

解析:在C语言中,变量必须先声明后使用(A错误),声明时可以不需要初始值(B错误),变量名不能包含空格(D错误)。

3. 下列代码的输出结果是?

int a = 5;
int b = a++;
printf("%d", a);
A. 5
B. 6
C. 0
D. 程序错误

答案:B. 6

解析:a++是后置递增运算符,先使用a的值赋值给b,然后a自增1,所以a的值变为6。

4. 在C语言中,变量的作用域可以是?

A. 局部作用域
B. 全局作用域
C. 文件作用域
D. 以上都是

答案:D. 以上都是

解析:C语言中变量可以具有局部作用域(在函数内部)、全局作用域(在所有函数外部)或文件作用域(使用static关键字)。

5. 下列哪个数据类型占用内存空间最小?

A. int
B. float
C. char
D. double

答案:C. char

解析:char类型通常占用1字节,int和float通常占用4字节,double通常占用8字节。

位运算

位运算是指对操作数以二进制位(bit)为单位进行的数据处理。每一个二进制位只能存放一位二进制数"0"或"1"。

位运算符

运算符 含义 优先级 格式
~ 取反 2 ~a
<< 左移n位 5 a<<n
>> 右移n位 5 b>>n
& 按位与 8 a&b
^ 按位异或 9 a^b
| 按位或 10 a|b

取反运算是单目运算,其余为双目运算。运算的操作数只能是整数或字符型数据,不能为实型数据。

逻辑位运算符的求值规律

a b ~a a&b a^b a|b
1 1 0 1 0 1
1 0 0 1 1
0 1 1 0 1 1
0 0 0 0 0

从表中可以得出以下结论:

① ~运算,0变1,1变0。

② &运算,当两个对应位均为1时,结果为1,否则为0。

③ ^运算,当两个对应位不同时,结果为1,否则为0。

④ |运算,当两个对应位均为0时,结果为0,否则为1。

代码示例

unsigned char a = 2, b = 4, c = 5, d = 16, e = 7, y;
y = a & b;      // y = (00000010) & (00000100) = 0
y = a | b;      // y = (00000010) | (00000100) = (00000110) = 6
y = a ^ c;      // y = (00000010) ^ (00000101) = (00000111) = 7
y = a << 2;     // y = (00000010) << 2 = (00001000) = 8
y = d >> 2;     // y = (00010000) >> 2 = (00000100) = 4
y = ~e;         // y = ~(00000111) = (11111000) = 248
y = d & e << 2; // y = d & (e << 2) = (00010000) & (00011100) = (00010000) = 16

练习题

1. 表达式 13 & 17 的值是?

A. 1
B. 13
C. 17
D. 29

答案:A. 1

解析:13的二进制是1101,17的二进制是10001,按位与操作后得到00001,即1。

2. 表达式 5 | 12 的值是?

A. 5
B. 12
C. 13
D. 17

答案:C. 13

解析:5的二进制是0101,12的二进制是1100,按位或操作后得到1101,即13。

3. 表达式 9 << 2 的值是?

A. 9
B. 18
C. 36
D. 72

答案:C. 36

解析:9的二进制是1001,左移2位后得到100100,即36。

4. 表达式 ~0 的值是?

A. 0
B. 1
C. -1
D. 最大值

答案:C. -1

解析:0的二进制表示全为0,按位取反后全为1,在补码表示中全1表示-1。

5. 表达式 15 ^ 9 的值是?

A. 6
B. 15
C. 9
D. 24

答案:A. 6

解析:15的二进制是1111,9的二进制是1001,按位异或操作后得到0110,即6。

强制类型转换

强制类型转换是将表达式的结果类型强制转换成指定类型的操作。

强制类型转换运算符

运算符为(类型),优先级为2。

格式: (类型)表达式

功能: 将表达式的结果类型强制转换成指定类型。

代码示例

(int) 3.14        // 结果为整型3
(float) 1         // 结果为浮点型1.0
1 / 2             // 结果为0
(float) 1 / 2     // 结果为0.5

注意:类型名应加圆括号。例如,float(2+5)是错误的,正确的写法是(float)(2+5)

练习题

1. 表达式 (int)3.14 + 5.2 的值是?

A. 8.2
B. 8.34
C. 8
D. 8.0

答案:A. 8.2

解析:(int)3.14将3.14转换为整型3,然后3+5.2=8.2。

2. 表达式 (float)(5/2) 的值是?

A. 2
B. 2.0
C. 2.5
D. 3.0

答案:B. 2.0

解析:5/2是整数除法,结果为2,然后强制转换为float类型,结果为2.0。

3. 表达式 (int)(7.5 + 3.2) 的值是?

A. 10
B. 10.7
C. 11
D. 10.0

答案:A. 10

解析:7.5+3.2=10.7,然后强制转换为int类型,结果为10。

4. 下列哪个表达式的结果是2.5?

A. (int)(5.0/2)
B. (float)5/2
C. 5/2
D. (int)5.0/2

答案:B. (float)5/2

解析:(float)5/2将5转换为float类型,然后除以2,结果为2.5。其他选项:A结果为2.0,C结果为2,D结果为2.0。

5. 关于强制类型转换,以下说法正确的是?

A. 会改变原变量的类型
B. 只影响当前表达式的计算
C. 只能用于数值类型
D. 不需要使用圆括号

答案:B. 只影响当前表达式的计算

解析:强制类型转换只是临时改变表达式的类型,不会改变原变量的类型。它可以用于各种类型,但必须使用圆括号。

知识点总结与易错点

知识点总结

  • 变量:需要先声明后使用,具有特定的数据类型和作用域
  • 位运算:对二进制位进行操作,包括取反(~)、左移(<<)、右移(>>)、按位与(&)、按位异或(^)、按位或(|)
  • 强制类型转换:使用(类型)运算符,临时改变表达式的类型

易错点

  • 混淆位运算(&,|,^)和逻辑运算(&&,||,!)
  • 忘记位运算只能用于整数和字符类型,不能用于浮点数
  • 混淆左移/右移运算符的方向
  • 忘记强制类型转换的优先级,导致意外的计算结果
  • 混淆整数除法和浮点数除法的结果
  • 忘记强制类型转换不会改变原变量的类型

综合练习题

1. 表达式 3 & 5 | 2 的值是?

A. 1
B. 2
C. 3
D. 7

答案:C. 3

解析:先计算3&5=1,然后1|2=3。

2. 表达式 (float)(10/3) 的值是?

A. 3
B. 3.0
C. 3.333...
D. 3.3

答案:B. 3.0

解析:10/3是整数除法,结果为3,然后强制转换为float类型,结果为3.0。

3. 表达式 8 >> 1 + 1 的值是?

A. 2
B. 4
C. 8
D. 16

答案:A. 2

解析:加法优先级高于移位运算符,所以先计算1+1=2,然后8>>2=2。

4. 下列代码的输出结果是?

int a = 5, b = 2;
float c = (float)a / b;
printf("%.1f", c);
A. 2
B. 2.0
C. 2.5
D. 5.0

答案:C. 2.5

解析:将a强制转换为float类型,然后除以2,结果为2.5。

5. 表达式 ~1 & 3 的值是?

A. 0
B. 1
C. 2
D. 3

答案:C. 2

解析:~1的二进制是11111110(假设8位),3的二进制是00000011,按位与操作后得到00000010,即2。