一,算数运算符
基本算术运算符:
加法(+):用于两个数相加。例如 int a = 3 + 5;,结果 a 的值为 8。
减法(-):两个数相减。如 int b = 7 - 4;,b 的值为 3。
乘法(*):两数相乘。int c = 2 * 6;,c 为 12。
除法(/):整数除法会截断结果的小数部分。例如 int d = 10 / 3;,d 的值为 3。
取余(%):也叫模运算,用于计算两个整数相除的余数。例如 int e = 10 % 3;,e 的值为 1。
运行结果:
自增和自减运算符:
自增(++):使变量的值增加 1。分为前置和后置两种形式。前置自增(如 ++a)先将变量的值加 1,然后再使用变量的值;后置自增(如 a++)先使用变量的值,然后再将变量的值加 1。自减(--):使变量的值减少 1,也有前置和后置两种形式。
运行结果:
二,关系运算符
一、等于运算符(==)
-
作用:判断两个值是否相等。
- 例如:
if (a == b)
,如果变量a
的值等于变量b
的值,那么这个条件判断为真。 - 不仅可以用于基本数据类型(如整数、浮点数、字符等)的比较,也可以用于指针的比较(判断两个指针是否指向同一个地址)。
- 例如:
-
注意事项:
- 与赋值运算符(=)容易混淆。赋值运算符是将一个值赋给一个变量,而等于运算符是判断两个值是否相等。例如,
if (a = 5)
是错误的用法,应该是if (a == 5)
。
- 与赋值运算符(=)容易混淆。赋值运算符是将一个值赋给一个变量,而等于运算符是判断两个值是否相等。例如,
二、不等于运算符(!=)
-
作用:判断两个值是否不相等。
- 例如:
if (a!= b)
,如果变量a
的值不等于变量b
的值,那么这个条件判断为真。 - 同样可以用于各种数据类型和指针的比较。
- 例如:
-
注意事项:与等于运算符相对应,在使用时要注意逻辑的正确性。
三、大于运算符(>)
-
作用:判断左边的值是否大于右边的值。
- 例如:
if (a > b)
,如果变量a
的值大于变量b
的值,那么这个条件判断为真。 - 适用于数值类型的比较,对于字符类型,实际上是比较其对应的 ASCII 码值。
- 例如:
-
注意事项:只能用于可比较大小的数据类型,对于没有大小关系的数据类型(如结构体,除非自定义了比较函数)不能使用。
四、小于运算符(<)
-
作用:判断左边的值是否小于右边的值。
- 例如:
if (a < b)
,如果变量a
的值小于变量b
的值,那么这个条件判断为真。 - 与大于运算符类似,适用于数值类型和字符类型的比较。
- 例如:
-
注意事项:同样要注意数据类型的适用性。
五、大于等于运算符(>=)
-
作用:判断左边的值是否大于或等于右边的值。
- 例如:
if (a >= b)
,如果变量a
的值大于或等于变量b
的值,那么这个条件判断为真。 - 在需要判断一个值是否在某个范围之上(包括边界值)时非常有用。
- 例如:
-
注意事项:确保比较的逻辑符合预期。
六、小于等于运算符(<=)
-
作用:判断左边的值是否小于或等于右边的值。
- 例如:
if (a <= b)
,如果变量a
的值小于或等于变量b
的值,那么这个条件判断为真。 - 常用于判断一个值是否在某个范围之下(包括边界值)。
- 例如:
-
注意事项:与其他关系运算符一样,注意数据类型和逻辑的正确性。
关系运算符通常在条件判断语句(如 if 语句、while 循环等)中使用,以控制程序的流程根据不同的比较结果执行不同的代码分支。
运行结果:
三,逻辑运算符
一、逻辑与运算符(&&)
-
作用:
- 当且仅当两个条件都为真时,整个表达式的结果才为真。如果其中任何一个条件为假,那么整个表达式的结果为假。
- 例如:
if (a > 0 && b < 10)
,只有当变量a
的值大于 0 并且变量b
的值小于 10 时,这个条件判断才为真。
-
短路特性:
- 如果第一个条件为假,那么就不会再去判断第二个条件,因为无论第二个条件的结果如何,整个表达式的结果都已经确定为假。
- 例如:
if ((a == NULL) && (a->value == 5))
,如果a
是一个指针且为NULL
,那么就不会去判断a->value == 5
这个条件,因为此时整个表达式已经确定为假,避免了因访问NULL
指针而导致的错误。
二、逻辑或运算符(||)
-
作用:
- 只要两个条件中有一个为真,整个表达式的结果就为真。只有当两个条件都为假时,整个表达式的结果才为假。
- 例如:
if (a == 5 || b == 8)
,如果变量a
的值等于 5 或者变量b
的值等于 8,那么这个条件判断就为真。
-
短路特性:
- 如果第一个条件为真,那么就不会再去判断第二个条件,因为无论第二个条件的结果如何,整个表达式的结果都已经确定为真。
- 例如:
if ((a!= NULL) || (b = allocateMemory()))
,如果a
不是NULL
,那么就不会去调用allocateMemory()
函数来判断第二个条件,因为此时整个表达式已经确定为真,避免了不必要的函数调用。
三、逻辑非运算符(!)
-
作用:
- 对一个条件取反。如果条件为真,那么
!
操作后结果为假;如果条件为假,那么!
操作后结果为真。 - 例如:
if (!(a > b))
,如果变量a
的值不大于变量b
的值,那么这个条件判断为真。
- 对一个条件取反。如果条件为真,那么
-
注意事项:
- 逻辑非运算符是一元运算符,只作用于一个条件表达式。
- 在使用时要注意逻辑的正确性,避免因取反而导致的意外结果。
逻辑运算符在 C 语言中广泛用于条件判断和控制程序的流程,通过组合多个条件可以实现复杂的逻辑判断。
运行结果:
四,位运算符
在 C 语言中,位运算符用于对二进制位进行操作。所以进行比较的时候是把我们常见的十进制数字转换为二进制数字,和其他语言不太一样,例如java语言的位运算符,有的也只是逻辑运算符的功能.
一、按位与运算符(&)
-
作用:
- 对应位都为 1 时结果为 1,否则为 0。
- 例如,假设
a = 5
(二进制为 0101),b = 3
(二进制为 0011),那么a & b
的结果为 1(二进制为 0001)。
-
应用场景:
- 可以用于提取某些特定的位。比如要判断一个整数的最低位是否为 0,可以将这个整数与 1(二进制为 0001)进行按位与操作,如果结果为 0,则最低位为 0。
- 用于清除某些特定的位。将一个数与一个所有要清除的位为 0 的数进行按位与操作,就可以将这些位清为 0。
二、按位或运算符(|)
-
作用:
- 对应位只要有一个为 1 时结果为 1。
- 例如,对于上面的
a = 5
和b = 3
,a | b
的结果为 7(二进制为 0111)。
-
应用场景:
- 设置某些特定的位。将一个数与一个所有要设置的位为 1 的数进行按位或操作,就可以将这些位设置为 1。
- 合并两个标志或状态。如果不同的位代表不同的状态,可以使用按位或操作来合并两个状态。
三、按位异或运算符(^)
-
作用:
- 对应位不同时结果为 1。
- 例如,
a = 5
和b = 3
,a ^ b
的结果为 6(二进制为 0110)。
-
应用场景:
- 交换两个变量的值而不使用临时变量。例如,
a = a ^ b; b = a ^ b; a = a ^ b;
,通过三次异或操作可以实现a
和b
的值交换。 - 加密和解密。在一些简单的加密算法中,可以使用异或操作对数据进行加密,然后再用相同的密钥进行异或操作来解密。
- 交换两个变量的值而不使用临时变量。例如,
四、左移运算符(<<)
-
作用:
- 将一个数的二进制位向左移动指定的位数。左边移出的位被丢弃,右边补 0。
- 例如,
a = 5
,a << 2
的结果为 20(二进制为 10100)。
-
应用场景:
- 快速实现乘以 2 的幂次方的操作。将一个数左移
n
位,相当于乘以 2 的n
次方。 - 在某些位操作场景中,用于调整位的位置。
- 快速实现乘以 2 的幂次方的操作。将一个数左移
五、右移运算符(>>)
-
作用:
- 将一个数的二进制位向右移动指定的位数。如果是无符号数,左边补 0;如果是有符号数,根据符号位进行填充(正数补 0,负数补 1)。
- 例如,
a = -5
(二进制为 11111111111111111111111111111011),a >> 2
的结果为 -2(二进制为 11111111111111111111111111111110)。
-
应用场景:
- 快速实现除以 2 的幂次方的操作。将一个数右移
n
位,相当于除以 2 的n
次方。 - 在某些需要对二进制位进行调整的场景中使用。
- 快速实现除以 2 的幂次方的操作。将一个数右移
运算结果:
运算结果:
五,赋值运算符
一、基本赋值运算符(=)
-
作用:
- 将右侧的值赋给左侧的变量。
- 例如,
int a = 5;
,这里将整数 5 赋值给变量a
。
-
注意事项:
- 左侧必须是一个可修改的左值,通常是变量名、数组元素或指针所指向的内存位置等。
- 赋值运算符的优先级相对较低,在复杂表达式中要注意使用括号来明确运算顺序。
二、复合赋值运算符
-
加法赋值运算符(+=):
- 作用:先将左侧变量的值与右侧的值相加,然后将结果再赋给左侧变量。
- 例如,
int b = 3; b += 2;
,相当于b = b + 2;
,执行后b
的值为 5。
-
减法赋值运算符(-=):
- 作用:先将左侧变量的值减去右侧的值,然后将结果再赋给左侧变量。
- 例如,
int c = 5; c -= 3;
,相当于c = c - 3;
,执行后c
的值为 2。
-
乘法赋值运算符(*=):
- 作用:先将左侧变量的值与右侧的值相乘,然后将结果再赋给左侧变量。
- 例如,
int d = 4; d *= 3;
,相当于d = d * 3;
,执行后d
的值为 12。
-
除法赋值运算符(/=):
- 作用:先将左侧变量的值除以右侧的值,然后将结果再赋给左侧变量。
- 例如,
int e = 10; e /= 2;
,相当于e = e / 2;
,执行后e
的值为 5。注意,如果右侧的值为 0,会导致运行时错误。
-
取余赋值运算符(%=):
- 作用:先将左侧变量的值与右侧的值进行取余运算,然后将结果再赋给左侧变量。
- 例如,
int f = 11; f %= 4;
,相当于f = f % 4;
,执行后f
的值为 3。
复合赋值运算符的优点在于可以使代码更加简洁,并且在某些情况下可以提高程序的执行效率,因为编译器可能会对复合赋值运算符进行一些优化。
六,逗号运算符和三目运算符
1,逗号运算符
(1)、逗号运算符的作用
-
连接多个表达式:
- 逗号运算符可以将多个表达式依次连接起来,从左到右依次计算每个表达式的值。
- 例如:
int a = 1, b = 2, c = 3;
,这里使用逗号运算符同时声明并初始化了三个变量。
-
确定整个逗号表达式的值:
- 逗号表达式的值是最后一个表达式的值。
- 例如:
int x; x = (a = 5, b = a + 2, c = b * 3);
,这里先给a
赋值为 5,然后b
被赋值为a + 2
即 7,接着c
被赋值为b * 3
即 21,最后整个逗号表达式的值为 21,所以x
的值为 21。
(2)、逗号运算符的应用场景
-
在 for 循环中:
- 逗号运算符在 for 循环的初始化和更新部分经常被使用,可以同时初始化多个变量或进行多个变量的更新操作。
- 例如:
for (int i = 0, j = 10; i < j; i++, j--) { /* loop body */ }
,这里在 for 循环的初始化部分同时初始化了两个变量i
和j
,在更新部分同时对i
进行自增和对j
进行自减操作。
-
函数参数列表中:
- 在一些函数调用中,可以使用逗号运算符将多个参数连接起来传递给函数。
- 例如:
printf("%d, %d\n", a, (b = 5, b + 2));
,这里先给b
赋值为 5,然后计算b + 2
的值为 7,最后将a
的值和 7 依次传递给printf
函数进行输出。
-
复杂表达式中:
- 在一些复杂的表达式中,可以使用逗号运算符来组织多个子表达式,使代码更加清晰。
- 例如:
int result = ((a > b)? a : b, (c > d)? c : d);
,这里先根据条件判断选择a
和b
中的较大值,然后选择c
和d
中的较大值,最后整个逗号表达式的值是c
和d
中的较大值,所以result
的值为c
和d
中的较大值。
实例:
2,三目运算符
(1)、三目运算符的形式和作用
-
形式:
- 表达式 1? 表达式 2 : 表达式 3。
-
作用:
-
首先计算表达式 1,如果表达式 1 的值为真(非零值),则整个三目运算符的结果为表达式 2 的值;如果表达式 1 的值为假(零值),则整个三目运算符的结果为表达式 3 的值。
-
例如:
int max = (a > b)? a : b;
,如果变量a
的值大于变量b
的值,那么max
的值为a
;否则,max
的值为b
。
-
(2)、三目运算符的应用场景
-
简洁的条件赋值:
- 当需要根据一个条件进行赋值操作时,三目运算符可以提供一种简洁的方式。
- 例如:
int flag = (condition)? 1 : 0;
,如果condition
为真,则flag
被赋值为 1;否则,flag
被赋值为 0。
-
在函数调用中:
- 可以根据条件选择不同的函数参数进行函数调用。
- 例如:
printf("%s\n", (flag)? "True" : "False");
,根据flag
的值打印不同的字符串。
-
在表达式中简化条件判断:
- 在一些复杂的表达式中,可以使用三目运算符来简化条件判断。
- 例如:
int result = (a > b)? (a + c) : (b + c);
,根据a
和b
的大小关系选择不同的表达式进行计算。
(3)、三目运算符的注意事项
-
可读性:
- 虽然三目运算符可以使代码更加简洁,但在某些情况下,过度使用可能会降低代码的可读性。如果条件和结果表达式非常复杂,使用 if-else 语句可能会使代码更易于理解。
-
优先级:
- 三目运算符的优先级较低,在复杂表达式中要注意使用括号来明确运算顺序,以避免出现意外的结果。
实例:
运行结果:
七,运算符的优先级
(这很关键)
优先级 | 运算符 | 结合律 |
1 | 后缀运算符: [] () · -> ++ --(类型名称){列表} | 从左到右 |
2 | 一元运算符: ++ -- ! ~ + - * & sizeof_Alignof | 从右到左 |
3 | 类型转换运算符: (类型名称) | 从右到左 |
4 | 乘除法运算符: * / % | 从左到右 |
5 | 加减法运算符: + - | 从左到右 |
6 | 移位运算符: << >> | 从左到右 |
7 | 关系运算符: <<= >>= | 从左到右 |
8 | 相等运算符: == != | 从左到右 |
9 | 位运算符 AND: & | 从左到右 |
10 | 位运算符 XOR: ^ | 从左到右 |
11 | 位运算符 OR: | | 从左到右 |
12 | 逻辑运算符 AND: && | 从左到右 |
13 | 逻辑运算符 OR: || | 从左到右 |
14 | 条件运算符: ?: | 从右到左 |
15 | 赋值运算符: = += -= *= /= %= &= ^= |= <<= >>= | 从右到左 |
16 | 逗号运算符:, | 从左到右 |
Tips:
<1>表中优先级最高的运算符中的最后一个(类型名称) {列表} 是 C99 新增加的。
<2>一些运算符记号在表中出现了两次。例如,自增运算符 ++ 和自减运算符 --,在作后缀运算符(如表]达式 x++)时,较其用作前缀运算符(如表达式 ++x)时,具有较高的优先级。
<3>+、 -、 * 和 & 运算符记号不但可以当作一元运算符(unary operator,只需要一个操作数),也可以当作二元运算符(binary operator,需要两个操作数)。例如, * 只有一个操作数的时候,就是间接运算符(indirection operator),而有两个操作数的时候,就是乘号。
简单速记: ! > 算术运算 > 关系运算 > 逻辑运算 > 赋值运算
有个简单的小问题,思考一下:定义三个整数a,b,c,并从键盘进行赋值,然后进行排序。最终输出,a保存最小值, b保存其次, c保存最大值.
例如:
用户输入 a = 30,b = 20,c = 10.要求最终保存的结果为
a = 10,b = 20,c = 30