#C 语言的基本运算
运算就是用值来做各种变化的游戏,例如 1 + 1
得到 2
,其中 +
是加法的运算符。
#赋值运算符
C 语言使用 =
作为赋值运算符,用于修改变量的值,而非数学中的“等于”。
实例:
#include <stdio.h>
int main(void)
{
int x = 10; // 定义变量 x
printf("%d\n", x);
x = 233; // 修改变量的值
printf("%d\n", x);
return 0;
}
运行结果:
10 233
#算术运算符
算术运算符用于进行算术运算。
运算符 | 名称 | 示例 | 结果 | 说明 |
---|---|---|---|---|
+ | 加法运算符 | 3 + 5 | 7 | - |
- | 减法运算符 | 5 - 3 | 2 | - |
* | 乘法运算符 | 5 * 3 | 15 | - |
/ | 除法运算符 | 5 / 2 | 2 | 整型的运算结果是整型,浮点型的运算结果是浮点型 |
% | 取余运算符 | 5 % 2 | 1 | 5 除以 2,得 2 余 1 |
示例:
#include <stdio.h>
int main(void)
{
printf("%d + %d = %d\n", 10, 3, 10 + 3);
printf("%d - %d = %d\n", 10, 3, 10 - 3);
printf("%d * %d = %d\n", 10, 3, 10 * 3);
printf("%d / %d = %d\n", 10, 3, 10 / 3); // 10 除以 3 得 3 余数 1,整型运算结果取整,因此结果为 3
printf("%d %% %d = %d\n", 10, 3, 10 % 3); // 10 除以 3 得 3 余数 1,因此结果为 1
printf("%f / %f = %f\n", 10.0, 3.0, 10.0 / 3.0); // 10.0 除以 3.0 得 3.333333
printf("%f / %d = %f\n", 10.0, 3, 10.0 / 3); // double 与 int 进行运算,int 隐式转换为 double,得 3.333333
return 0;
}
10 / 3
是int
除以int
,结果取整得 310.0 / 3.0
是double
除以double
,结果是 3.3333310.0 / 3
是double
除以int
,int
隐式转换为double
,实际进行double
除以double
的运算
运行结果:
10 + 3 = 13 10 - 3 = 7 10 * 3 = 30 10 / 3 = 3 10 % 3 = 1 10.000000 / 3.000000 = 3.333333 10.000000 / 3 = 3.333333
#正负号
运算符 | 名称 | 示例 |
---|---|---|
+ | 正号 | +3 |
- | 负号 | -5 |
#比较运算符
比较运算符用于比较两个值的关系,结果为 true
(真) 或 false
(假)。
运算符 | 名称 | 示例 | 结果 |
---|---|---|---|
== | 等于运算符 | 3 == 5 | 0 |
!= | 不等于运算符 | 3 != 5 | 1 |
> | 大于运算符 | 5 > 3 | 1 |
< | 小于运算符 | 5 < 2 | 0 |
>= | 大于或等于运算符 | 5 >= 5 | 1 |
<= | 小于或等于运算符 | 5 <= 2 | 0 |
#逻辑运算符
逻辑运算符用于逻辑运算。
运算符 | 名称 | 示例 | 结果 | 说明 |
---|---|---|---|---|
&& | 逻辑与运算符 | true && false | false | 全部为 true 时结果为 true ,否则结果为 false |
|| | 逻辑或运算符 | true || false | true | 全部为 false 时结果为 false ,否则结果为 true |
! | 逻辑非运算符 | ! false | true | 将一个布尔值反转 |
true
为 1,false
为 0,并且所有非零的值均视为true
;参考 布尔类型。
在 C23 标准之前需要包含 stdbool.h 头文件才能直接使用
bool
类型以及true
和false
;
否则,只能使用int
类型以及 1 和 0 代替。
示例:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
// true 和 false 的值是 1 和 0
printf("true = %d\n", true);
printf("false = %d\n", false);
// 逻辑非
printf("!true = %d\n", !true);
printf("!false = %d\n", !false);
// 逻辑与
printf("true && true = %d\n", true && true);
printf("true && false = %d\n", true && false);
printf("false && true = %d\n", false && true);
printf("false && false = %d\n", false && false);
// 逻辑或
printf("true || true = %d\n", true || true);
printf("true || false = %d\n", true || false);
printf("false || true = %d\n", false || true);
printf("false || false = %d\n", false || false);
// 非零值均视为 true
printf("!10 = %d\n", !10);
printf("10 && 10 = %d\n", 10 && 10);
printf("10 && 0 = %d\n", 10 && 0);
printf("10 || 0 = %d\n", 10 || 0);
return 0;
}
运行结果:
true = 1 false = 0 !true = 0 !false = 1 true && true = 1 true && false = 0 false && true = 0 false && false = 0 true || true = 1 true || false = 1 false || true = 1 false || false = 0 !10 = 0 10 && 10 = 1 10 && 0 = 0 10 || 0 = 1
逻辑运算中存在一个名为短路原则(Short-circuit evaluation)的特性——在逻辑运算中,如果前面的部分运算已经能够确定整个运算的结果,就不再计算后面的表达式。
- 对于
A && B
,如果A
为false
,则无论B
是什么,整个表达式的结果都必定是false
,因此不会计算B
。 - 对于
A || B
,如果A
为true
,则无论B
是什么,整个表达式的结果都必定是true
,因此不会计算B
。
示例:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int x = 10;
false && (x = 1); // x = 1 不会被执行
true || (x = 2); // x = 2 不会被执行
printf("x 的值是 %d\n", x);
return 0;
}
运行结果:
x 的值是 10
#位运算符
位运算符用于二进制位运算。
运算符 | 名称 | 示例 | 结果 | 说明 |
---|---|---|---|---|
& | 位与运算符 | 0b1100 & 0b0110 | 0b0100 | 按二进制位进行计算,两个数在某一位上都是 1 ,则结果在该位为 1 ,否则结果在该位为 0 |
| | 位或运算符 | 0b1100 | 0b0110 | 0b1110 | 按二进制位进行计算,两个数在某一位上都是 0 ,则结果在该位为 0 ,否则结果在该位为 1 |
^ | 异或运算符 | 0b1100 ^ 0b0110 | 0b1010 | 二进制中不同的位结果为 1 ,相同的位结果位 0 |
<< | 左移运算符 | 0b0011 << 2 | 0b1100 | 二进制位向左移动,右侧补 0 |
>> | 右移运算符 | 0b1100 >> 1 | 0b0110 | 二进制位向右移动,左侧补 0 |
~ | 取反运算符 | ~0b1100 | 0b0011 | 二进制位取反,即 1 变为 0 ,0 变为 1 |
C 语言标准并不支持二进制字面量,表格中示例的二进制写法仅作用演示。
示例:
#include <stdio.h>
int main(void)
{
printf("%#x & %#x = %#x\n", 0xfff0, 0x0fff, 0xfff0 & 0x0fff);
printf("%#x | %#x = %#x\n", 0xfff0, 0x0fff, 0xfff0 | 0x0fff);
printf("%#x ^ %#x = %#x\n", 0xfff0, 0x0fff, 0xfff0 ^ 0x0fff);
printf("%#x << %d = %#x\n", 0xfff0, 4, 0xfff0 << 4);
printf("%#x >> %d = %#x\n", 0xfff0, 4, 0xfff0 >> 4);
printf("~%#x = %#x\n", 0xfff0, ~0xfff0);
return 0;
}
运行结果:
0xfff0 & 0xfff = 0xff0 0xfff0 | 0xfff = 0xffff 0xfff0 ^ 0xfff = 0xf00f 0xfff0 << 4 = 0xfff00 0xfff0 >> 4 = 0xfff ~0xfff0 = 0xffff000f
#复合赋值运算符
复合赋值运算符是一种将运算和赋值合并的简化写法,它将变量的值进行计算后再赋值给该变量。例如 x += 1
相当于 x = x + 1
。
运算符 | 等价写法 | 说明 |
---|---|---|
+= | a += b -> a = a + b | 加并赋值 |
-= | a -= b -> a = a - b | 减并赋值 |
*= | a *= b -> a = a * b | 乘并赋值 |
/= | a /= b -> a = a / b | 除并赋值 |
%= | a %= b -> a = a % b | 取模并赋值 |
<<= | a <<= b -> a = a << b | 左移并赋值 |
>>= | a >>= b -> a = a >> b | 右移并赋值 |
&= | a &= b -> a = a & b | 按位与并赋值 |
|= | a |= b -> a = a | b | 按位或并赋值 |
^= | a ^= b -> a = a ^ b | 按位异或并赋值 |
示例:
#include <stdio.h>
int main(void)
{
int x = 10;
x += 2; // x = x + 2 -> 12
printf("%d\n", x);
x -= 3; // x = x - 3 -> 9
printf("%d\n", x);
x *= 4; // x = x * 4 -> 36
printf("%d\n", x);
x /= 5; // x = x / 2 -> 7
printf("%d\n", x);
return 0;
}
运行结果:
12 9 36 7
#自增与自减
运算符 | 说明 |
---|---|
x++ | x = x + 1 ,返回 x 加一之前的值 |
x-- | x = x - 1 ,返回 x 减一之前的值 |
++x | x = x + 1 ,返回 x 加一之后的值 |
--x | x = x - 1 ,返回 x 减一之后的值 |
示例:
#include <stdio.h>
int main(void)
{
int x = 10;
printf("%d\n", x++); // x = x + 1,返回 x 加一之前的值,因此打印 10
printf("%d\n", x); // x 的值是 11
int y = 10;
printf("%d\n", ++y); // y = y + 1,返回 x 加一之后的值,因此打印 11
printf("%d\n", y); // y 的值是 11
return 0;
}
运行结果:
10 11 11 11
#运算符优先级
运算符存在优先级,和数学一样先乘除,后加减。例如
括号为最高优先级,可以使用括号改变计算顺序。例如
下表为优先级列表,优先级由高到低:
优先级 | 运算符 | 结合性 |
---|---|---|
最高 | x++ x-- () [] . -> (type){list} | 从左向右 |
2 | ++x --x +x -x (type) * &x sizeof _Alignof | 从右向左 |
3 | * / % | 从左向右 |
4 | + - | 从左向右 |
5 | << >> | 从左向右 |
6 | < <= > >= | 从左向右 |
7 | == != | 从左向右 |
8 | & | 从左向右 |
9 | ^ | 从左向右 |
10 | | | 从左向右 |
11 | && | 从左向右 |
12 | || | 从左向右 |
13 | ?: | 从右向左 |
14 | = += -= *= /= %= <<= >>= &= ^= |= | 从右向左 |
最低 | , | 从左向右 |