一、C 运算符
C语言中的运算符是用于执行各种操作的符号。这些运算符可以分为几类,包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符(也称为三元运算符)等。以下是这些运算符的一些例子和描述:
- 算术运算符:
+
加法-
减法*
乘法/
除法%
取模(求余数)++
自增--
自减
- 关系运算符(也称为比较运算符):
==
等于!=
不等于>
大于<
小于>=
大于或等于<=
小于或等于
- 逻辑运算符:
&&
逻辑与(AND)||
逻辑或(OR)!
逻辑非(NOT)
- 位运算符:
&
按位与(AND)|
按位或(OR)^
按位异或(XOR)~
按位取反(NOT)<<
左移>>
右移
- 赋值运算符:
=
赋值+=
加等于(例如a += b;
相当于a = a + b;
)-=
减等于*=
乘等于/=
除等于%=
取模等于
- 条件运算符(三元运算符):
(condition) ? (expression_if_true) : (expression_if_false)
- 其他运算符:
sizeof
返回类型或对象的大小(以字节为单位)&
地址运算符(返回变量的内存地址)*
指针解引用运算符(返回指针指向的变量的值).
结构体成员访问运算符->
结构体指针成员访问运算符()
函数调用、运算符优先级调整等
- 逗号运算符:
,
逗号运算符允许将多个表达式组合成一个表达式,并返回最后一个表达式的值。它主要用于循环和宏定义中。
在使用这些运算符时,需要注意它们的优先级和结合性。例如,乘法(*
)和除法(/
)的优先级高于加法(+
)和减法(-
)。可以使用括号来改变表达式的计算顺序。
二、算术运算符
算术运算符的案例代码
#include <stdio.h>
int main() {
int a = 10;
int b = 5;
int c;
float d;
// 加法
c = a + b;
printf("a + b = %d\n", c);
// 减法
c = a - b;
printf("a - b = %d\n", c);
// 乘法
c = a * b;
printf("a * b = %d\n", c);
// 除法
c = a / b;
printf("a / b = %d\n", c);
// 取模(求余数)
c = a % b;
printf("a %% b = %d\n", c);
// 自增
a++;
printf("a++ = %d\n", a);
// 自减
b--;
printf("b-- = %d\n", b);
// 浮点数的算术运算
d = a / 2.0; // 注意:整数除法会丢失小数部分
printf("a / 2.0 (as float) = %f\n", d);
d = (float)a / 2.0; // 强制转换为浮点数再除
printf("(float)a / 2.0 = %f\n", d);
// 复合赋值运算符
a += 3; // 相当于 a = a + 3;
printf("a += 3 = %d\n", a);
return 0;
}
这段代码演示了如何使用C语言中的基本算术运算符。当涉及到整数和浮点数混合运算时,需要注意整数除法会丢失小数部分,除非至少有一个操作数是浮点数。在d = a / 2.0;
这行代码中,尽管除数是一个浮点数,但由于a
是整数,所以整个表达式的结果仍然会被截断为整数。为了得到浮点数的结果,我们需要将a
显式地转换为浮点数,如d = (float)a / 2.0;
所示。
三、关系运算符
关系运算符(也称为比较运算符)的案例代码
#include <stdio.h>
int main() {
int a = 10;
int b = 5;
// 等于
if (a == b) {
printf("a is equal to b\n");
} else {
printf("a is not equal to b\n");
}
// 不等于
if (a != b) {
printf("a is not equal to b\n");
}
// 大于
if (a > b) {
printf("a is greater than b\n");
}
// 小于
if (a < b) {
printf("a is less than b\n");
} else {
printf("a is not less than b\n");
}
// 大于或等于
if (a >= b) {
printf("a is greater than or equal to b\n");
}
// 小于或等于
if (a <= b) {
// 注意:这个条件在上面的比较中已经为假,因为a大于b
// 这里只是为了演示语法
printf("a is less than or equal to b\n");
} else {
printf("a is not less than or equal to b\n");
}
return 0;
}
这段代码演示了如何使用C语言中的关系运算符来比较两个整数a
和b
的值,并根据比较结果执行相应的操作(在这里是打印消息到控制台)。关系运算符的结果是一个布尔值(在C语言中,这通常是通过非零值(真)和零值(假)来表示的)。这些结果随后被用于if
语句的条件部分,以决定程序的执行流程。
四、逻辑运算符
逻辑运算符的案例代码
#include <stdio.h>
int main() {
int a = 1;
int b = 0;
int c = 1;
// 逻辑与(AND)
if (a && b) {
printf("a AND b is true\n");
} else {
printf("a AND b is false\n");
}
// 逻辑或(OR)
if (a || b) {
printf("a OR b is true\n");
} else {
printf("a OR b is false\n");
}
// 逻辑非(NOT)
if (!b) {
printf("NOT b is true\n");
} else {
printf("NOT b is false\n");
}
// 结合使用逻辑运算符
if ((a && c) || (!b)) {
printf("The combined logical expression is true\n");
} else {
printf("The combined logical expression is false\n");
}
return 0;
}
这段代码演示了如何使用C语言中的逻辑运算符&&
(逻辑与)、||
(逻辑或)和!
(逻辑非)。逻辑运算符用于组合布尔表达式,并产生单个布尔结果。在这个例子中,我们使用了整数1
(在C语言中通常被解释为真)和0
(被解释为假)来演示逻辑运算。
a && b
检查a
和b
是否都为真。由于b
为假,所以整个表达式的结果为假。a || b
检查a
或b
是否有一个为真。由于a
为真,所以整个表达式的结果为真。!b
是对b
的逻辑非操作。由于b
为假,其逻辑非的结果为真。((a && c) || (!b))
是一个更复杂的逻辑表达式,它首先检查a
和c
是否都为真(它们都是),然后检查结果是否为真或b
是否为假(也是)。由于至少有一个条件为真,所以整个复合表达式的结果为真。
五、位运算符
位运算符的案例代码
#include <stdio.h>
int main() {
unsigned int a = 60; // 60 = 0011 1100 (in binary)
unsigned int b = 13; // 13 = 0000 1101 (in binary)
unsigned int c;
// 按位与(AND)
c = a & b;
printf("a & b = %u\n", c); // 输出: 12 = 0000 1100
// 按位或(OR)
c = a | b;
printf("a | b = %u\n", c); // 输出: 61 = 0011 1101
// 按位异或(XOR)
c = a ^ b;
printf("a ^ b = %u\n", c); // 输出: 49 = 0011 0001
// 按位取反(NOT)
c = ~a;
printf("~a = %u\n", c); // 输出: 一个很大的数,取决于unsigned int的大小和表示方式
// 左移(Left Shift)
c = a << 2;
printf("a << 2 = %u\n", c); // 输出: 240 = 1111 0000
// 右移(Right Shift)
c = a >> 1;
printf("a >> 1 = %u\n", c); // 输出: 30 = 0001 1110
return 0;
}
这段代码展示了如何使用C语言中的位运算符来操作整数的二进制表示。请注意,~
(按位取反)运算符的结果是一个很大的数,因为它反转了a
的所有位。由于a
是一个unsigned int
,其最高位(符号位)被解释为数值位的一部分,所以取反后得到的是一个非常大的数。
此外,左移和右移运算符分别用于将整数的所有位向左或向右移动指定的位数。左移操作相当于乘以2的幂,而右移操作相当于除以2的幂(对于无符号整数)。
请注意,这些示例中的二进制表示和结果可能因计算机系统和编译器的不同而略有差异,特别是当处理有符号整数时。上面的示例使用了unsigned int
来避免符号扩展的问题。
六、赋值运算符
赋值运算符的案例代码
#include <stdio.h>
int main() {
int a, b, c;
// 简单的赋值
a = 10;
printf("a = %d\n", a);
// 复合赋值运算符(加等于 +=)
a += 5; // 相当于 a = a + 5;
printf("a += 5, a = %d\n", a);
// 复合赋值运算符(减等于 -=)
a -= 3; // 相当于 a = a - 3;
printf("a -= 3, a = %d\n", a);
// 复合赋值运算符(乘等于 *=)
b = 2;
b *= 3; // 相当于 b = b * 3;
printf("b *= 3, b = %d\n", b);
// 复合赋值运算符(除等于 /=)
c = 10;
c /= 2; // 相当于 c = c / 2; 注意这里会进行整数除法
printf("c /= 2, c = %d\n", c);
// 复合赋值运算符(模等于 %=)
c %= 3; // 相当于 c = c % 3;
printf("c %= 3, c = %d\n", c);
// 复合赋值运算符也可以结合使用其他运算符
a = 5;
a *= a += 2; // 这里的顺序是先 a += 2, 然后 a *= (a的新值)
printf("a *= a += 2, a = %d\n", a); // 注意:这个表达式在某些编译器中可能会产生警告或错误,因为它依赖于未定义的行为(即顺序点)
return 0;
}
请注意,复合赋值运算符(如 +=
、-=
、*=
、/=
和 %=
)在表达式中同时进行计算和赋值操作,使得代码更加简洁。但是,在复杂的表达式中(如上面的 a *= a += 2;
),需要注意运算的顺序和可能的副作用,因为这样的表达式可能会导致未定义的行为。
在上面的代码中,a *= a += 2;
是不推荐使用的,因为它违反了C语言中的顺序点规则,可能导致不同的编译器产生不同的结果。在实际编程中,应该避免编写这样的表达式,而是将其拆分成多个清晰的步骤。