Appearance
运算符
运算符用于执行各种运算操作。C语言提供了丰富的运算符,包括算术运算符、关系运算符、逻辑运算符、位运算符等。本章将详细介绍C语言中的各类运算符。
算术运算符
c
/*
* 算术运算符
*/
#include <stdio.h>
int main(void)
{
int a = 10, b = 3;
/* 加法运算 */
printf("a + b = %d\n", a + b); /* 13 */
/* 减法运算 */
printf("a - b = %d\n", a - b); /* 7 */
/* 乘法运算 */
printf("a * b = %d\n", a * b); /* 30 */
/* 除法运算 */
printf("a / b = %d\n", a / b); /* 3(整数除法,截断小数) */
/* 取模运算(求余数) */
printf("a %% b = %d\n", a % b); /* 1 */
/* 浮点数除法 */
float fa = 10.0f, fb = 3.0f;
printf("fa / fb = %f\n", fa / fb); /* 3.333333 */
/* 注意:取模运算只能用于整数 */
/* printf("%f", 10.0 % 3.0); */ /* 错误 */
/* 负数取模 */
printf("-10 %% 3 = %d\n", -10 % 3); /* -1 */
printf("10 %% -3 = %d\n", 10 % -3); /* 1 */
printf("-10 %% -3 = %d\n", -10 % -3); /* -1 */
return 0;
}自增自减运算符
c
/*
* 自增自减运算符
*/
#include <stdio.h>
int main(void)
{
int a = 5;
int b;
/* 前置自增:先加1,再使用 */
b = ++a;
printf("++a: a = %d, b = %d\n", a, b); /* a=6, b=6 */
/* 后置自增:先使用,再加1 */
a = 5; /* 重置a的值 */
b = a++;
printf("a++: a = %d, b = %d\n", a, b); /* a=6, b=5 */
/* 前置自减:先减1,再使用 */
a = 5;
b = --a;
printf("--a: a = %d, b = %d\n", a, b); /* a=4, b=4 */
/* 后置自减:先使用,再减1 */
a = 5;
b = a--;
printf("a--: a = %d, b = %d\n", a, b); /* a=4, b=5 */
/* 复杂表达式中的自增自减 */
int x = 3;
int y = x++ + ++x; /* 未定义行为,应避免 */
printf("x = %d, y = %d\n", x, y);
/* 推荐写法:分开写 */
x = 3;
int temp1 = x;
x++;
int temp2 = x;
x++;
y = temp1 + temp2;
printf("推荐写法: x = %d, y = %d\n", x, y);
return 0;
}关系运算符
c
/*
* 关系运算符(比较运算符)
*/
#include <stdio.h>
#include <stdbool.h> /* C99布尔类型 */
int main(void)
{
int a = 10, b = 5;
/* 大于 */
printf("a > b: %d\n", a > b); /* 1(真) */
/* 小于 */
printf("a < b: %d\n", a < b); /* 0(假) */
/* 大于等于 */
printf("a >= b: %d\n", a >= b); /* 1 */
/* 小于等于 */
printf("a <= b: %d\n", a <= b); /* 0 */
/* 等于 */
printf("a == b: %d\n", a == b); /* 0 */
/* 不等于 */
printf("a != b: %d\n", a != b); /* 1 */
/* 注意:== 和 = 的区别 */
int x = 5;
if (x = 10) { /* 这是赋值,不是比较! */
printf("x被赋值为10\n");
}
/* 正确的比较 */
x = 5;
if (x == 10) {
printf("x等于10\n");
} else {
printf("x不等于10\n");
}
/* 推荐写法:常量放左边 */
if (10 == x) { /* 如果写成 10 = x 会编译错误 */
printf("x等于10\n");
}
return 0;
}逻辑运算符
c
/*
* 逻辑运算符
*/
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
/* 逻辑与(&&):两个都为真才为真 */
printf("1 && 1 = %d\n", 1 && 1); /* 1 */
printf("1 && 0 = %d\n", 1 && 0); /* 0 */
printf("0 && 1 = %d\n", 0 && 1); /* 0 */
printf("0 && 0 = %d\n", 0 && 0); /* 0 */
/* 逻辑或(||):有一个为真就为真 */
printf("\n1 || 1 = %d\n", 1 || 1); /* 1 */
printf("1 || 0 = %d\n", 1 || 0); /* 1 */
printf("0 || 1 = %d\n", 0 || 1); /* 1 */
printf("0 || 0 = %d\n", 0 || 0); /* 0 */
/* 逻辑非(!):真变假,假变真 */
printf("\n!1 = %d\n", !1); /* 0 */
printf("!0 = %d\n", !0); /* 1 */
/* 短路求值 */
int a = 5, b = 0;
/* && 短路:如果左边为假,右边不计算 */
if (b != 0 && a / b > 1) {
printf("不会执行这里\n");
} else {
printf("短路避免了除零错误\n");
}
/* || 短路:如果左边为真,右边不计算 */
if (a > 0 || b++ > 0) {
printf("a > 0为真,b++不执行\n");
}
printf("b = %d(仍然是0)\n", b);
/* 实际应用 */
int age = 25;
int has_id = 1;
/* 检查是否满足条件 */
if (age >= 18 && has_id) {
printf("可以进入\n");
}
return 0;
}位运算符
c
/*
* 位运算符
*/
#include <stdio.h>
void print_binary(int num)
{
/* 打印整数的二进制表示 */
for (int i = 31; i >= 0; i--) {
printf("%d", (num >> i) & 1);
if (i % 4 == 0 && i != 0) {
printf(" ");
}
}
printf("\n");
}
int main(void)
{
unsigned int a = 12; /* 二进制: 0000 1100 */
unsigned int b = 10; /* 二进制: 0000 1010 */
printf("a = %u (二进制: ", a);
print_binary(a);
printf("b = %u (二进制: ", b);
print_binary(b);
/* 按位与(&):两位都为1才为1 */
printf("\na & b = %u (二进制: ", a & b); /* 8 (0000 1000) */
print_binary(a & b);
/* 按位或(|):有一位为1就为1 */
printf("a | b = %u (二进制: ", a | b); /* 14 (0000 1110) */
print_binary(a | b);
/* 按位异或(^):两位不同为1,相同为0 */
printf("a ^ b = %u (二进制: ", a ^ b); /* 6 (0000 0110) */
print_binary(a ^ b);
/* 按位取反(~):0变1,1变0 */
printf("~a = %u (二进制: ", ~a);
print_binary(~a);
/* 左移(<<):左移n位,相当于乘以2^n */
printf("\na << 2 = %u (二进制: ", a << 2); /* 48 (0011 0000) */
print_binary(a << 2);
/* 右移(>>):右移n位,相当于除以2^n */
printf("a >> 2 = %u (二进制: ", a >> 2); /* 3 (0000 0011) */
print_binary(a >> 2);
/* 位运算应用 */
printf("\n=== 位运算应用 ===\n");
/* 判断奇偶 */
int num = 7;
if (num & 1) {
printf("%d 是奇数\n", num);
} else {
printf("%d 是偶数\n", num);
}
/* 交换两个数(不使用临时变量) */
int x = 5, y = 10;
printf("交换前: x = %d, y = %d\n", x, y);
x = x ^ y;
y = x ^ y;
x = x ^ y;
printf("交换后: x = %d, y = %d\n", x, y);
/* 设置某位为1 */
unsigned int flags = 0; /* 0000 0000 */
flags = flags | (1 << 3); /* 设置第3位为1 */
printf("设置第3位: %u\n", flags); /* 8 */
/* 清除某位为0 */
flags = flags & ~(1 << 3); /* 清除第3位 */
printf("清除第3位: %u\n", flags); /* 0 */
/* 检查某位是否为1 */
flags = 12; /* 0000 1100 */
if (flags & (1 << 2)) {
printf("第2位是1\n");
}
return 0;
}赋值运算符
c
/*
* 赋值运算符
*/
#include <stdio.h>
int main(void)
{
int a = 10; /* 基本赋值 */
printf("a = %d\n", a);
/* 复合赋值运算符 */
/* 加法赋值 */
a += 5; /* 等价于 a = a + 5 */
printf("a += 5: %d\n", a); /* 15 */
/* 减法赋值 */
a -= 3; /* 等价于 a = a - 3 */
printf("a -= 3: %d\n", a); /* 12 */
/* 乘法赋值 */
a *= 2; /* 等价于 a = a * 2 */
printf("a *= 2: %d\n", a); /* 24 */
/* 除法赋值 */
a /= 4; /* 等价于 a = a / 4 */
printf("a /= 4: %d\n", a); /* 6 */
/* 取模赋值 */
a %= 4; /* 等价于 a = a % 4 */
printf("a %%= 4: %d\n", a); /* 2 */
/* 位运算赋值 */
a = 12;
/* 按位与赋值 */
a &= 10; /* 等价于 a = a & 10 */
printf("a &= 10: %d\n", a); /* 8 */
/* 按位或赋值 */
a |= 5; /* 等价于 a = a | 5 */
printf("a |= 5: %d\n", a); /* 13 */
/* 按位异或赋值 */
a ^= 7; /* 等价于 a = a ^ 7 */
printf("a ^= 7: %d\n", a); /* 10 */
/* 左移赋值 */
a <<= 2; /* 等价于 a = a << 2 */
printf("a <<= 2: %d\n", a); /* 40 */
/* 右移赋值 */
a >>= 1; /* 等价于 a = a >> 1 */
printf("a >>= 1: %d\n", a); /* 20 */
/* 连续赋值 */
int b, c;
a = b = c = 5; /* 从右向左赋值 */
printf("a = %d, b = %d, c = %d\n", a, b, c);
return 0;
}条件运算符
c
/*
* 条件运算符(三元运算符)
*/
#include <stdio.h>
int main(void)
{
int a = 10, b = 5;
/* 基本语法:条件 ? 表达式1 : 表达式2 */
/* 条件为真返回表达式1,否则返回表达式2 */
int max = (a > b) ? a : b;
printf("最大值: %d\n", max);
int min = (a < b) ? a : b;
printf("最小值: %d\n", min);
/* 判断奇偶 */
int num = 7;
printf("%d是%s\n", num, (num % 2 == 0) ? "偶数" : "奇数");
/* 求绝对值 */
int x = -5;
int abs_x = (x >= 0) ? x : -x;
printf("|%d| = %d\n", x, abs_x);
/* 嵌套条件运算符 */
int score = 75;
char grade;
grade = (score >= 90) ? 'A' :
(score >= 80) ? 'B' :
(score >= 70) ? 'C' :
(score >= 60) ? 'D' : 'F';
printf("分数 %d 的等级: %c\n", score, grade);
/* 与if-else对比 */
/* 等价的if-else写法 */
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else if (score >= 70) {
grade = 'C';
} else if (score >= 60) {
grade = 'D';
} else {
grade = 'F';
}
return 0;
}逗号运算符
c
/*
* 逗号运算符
*/
#include <stdio.h>
int main(void)
{
int a, b, c;
/* 逗号运算符:从左到右依次执行,返回最后一个表达式的值 */
a = (b = 3, c = 5, b + c);
printf("a = %d, b = %d, c = %d\n", a, b, c); /* a=8, b=3, c=5 */
/* 在for循环中使用 */
int sum = 0;
for (int i = 1, j = 10; i <= j; i++, j--) {
sum += i + j;
}
printf("sum = %d\n", sum);
/* 注意:逗号运算符的优先级最低 */
int x = 3;
int y = (x + 1, x + 2, x + 3); /* y = x + 3 = 6 */
printf("y = %d\n", y);
/* 与逗号分隔符的区别 */
int arr[] = {1, 2, 3}; /* 这里的逗号是分隔符,不是运算符 */
printf("arr[0] = %d, arr[1] = %d, arr[2] = %d\n", arr[0], arr[1], arr[2]);
return 0;
}sizeof运算符
c
/*
* sizeof运算符
*/
#include <stdio.h>
int main(void)
{
/* sizeof用于基本类型 */
printf("sizeof(char) = %zu\n", sizeof(char));
printf("sizeof(int) = %zu\n", sizeof(int));
printf("sizeof(double) = %zu\n", sizeof(double));
/* sizeof用于变量 */
int a = 10;
printf("sizeof(a) = %zu\n", sizeof(a));
printf("sizeof a = %zu\n", sizeof a); /* 变量可以不加括号 */
/* sizeof用于数组 */
int arr[10];
printf("sizeof(arr) = %zu\n", sizeof(arr)); /* 整个数组的大小 */
printf("数组元素个数 = %zu\n", sizeof(arr) / sizeof(arr[0]));
/* sizeof用于表达式 */
printf("sizeof(a + 1.5) = %zu\n", sizeof(a + 1.5)); /* double的大小 */
/* sizeof用于指针 */
int *ptr;
printf("sizeof(ptr) = %zu\n", sizeof(ptr)); /* 指针的大小 */
/* sizeof返回size_t类型 */
size_t size = sizeof(int);
printf("size_t类型的大小: %zu\n", sizeof(size_t));
return 0;
}运算符优先级
c
/*
* 运算符优先级和结合性
*/
#include <stdio.h>
int main(void)
{
/* 优先级从高到低排列:
* 1. () [] -> . 从左到右
* 2. ! ~ ++ -- + - * & sizeof (类型) 从右到左
* 3. * / % 从左到右
* 4. + - 从左到右
* 5. << >> 从左到右
* 6. < <= > >= 从左到右
* 7. == != 从左到右
* 8. & 从左到右
* 9. ^ 从左到右
* 10. | 从左到右
* 11. && 从左到右
* 12. || 从左到右
* 13. ?: 从右到左
* 14. = += -= *= /= %= &= ^= |= <<= >>= 从右到左
* 15. , 从左到右
*/
int a = 5, b = 3, c = 2;
int result;
/* 乘除优先于加减 */
result = a + b * c;
printf("a + b * c = %d\n", result); /* 5 + 6 = 11 */
/* 使用括号改变优先级 */
result = (a + b) * c;
printf("(a + b) * c = %d\n", result); /* 8 * 2 = 16 */
/* 关系运算符优先于逻辑运算符 */
if (a > b && b > c) {
printf("a > b > c\n");
}
/* 赋值运算符优先级很低 */
int x, y, z;
x = y = z = 0; /* 从右到左赋值 */
printf("x = %d, y = %d, z = %d\n", x, y, z);
/* 复杂表达式 */
result = a + b > c && b != c || a < c;
/* 等价于: ((a + b) > c) && (b != c) || (a < c) */
printf("result = %d\n", result);
/* 建议:使用括号明确优先级 */
result = ((a + b) > c) && ((b != c) || (a < c));
printf("使用括号: result = %d\n", result);
return 0;
}类型转换运算符
c
/*
* 类型转换运算符
*/
#include <stdio.h>
int main(void)
{
/* 隐式类型转换 */
int a = 5;
double b = 2.5;
double c = a + b; /* int自动转换为double */
printf("隐式转换: %f\n", c);
/* 显式类型转换(强制转换) */
int x = 5, y = 2;
/* 整数除法 */
int int_result = x / y;
printf("整数除法: %d\n", int_result); /* 2 */
/* 浮点除法 */
double float_result = (double)x / y;
printf("浮点除法: %f\n", float_result); /* 2.5 */
/* 截断小数 */
double d = 3.7;
int i = (int)d;
printf("截断: %d\n", i); /* 3 */
/* 四舍五入 */
int rounded = (int)(d + 0.5);
printf("四舍五入: %d\n", rounded); /* 4 */
/* 指针类型转换 */
int num = 0x41424344;
char *ptr = (char *)#
printf("指针转换: %c\n", ptr[0]); /* 取决于字节序 */
return 0;
}小结
本章学习了:
- 算术运算符:+、-、*、/、%、++、--
- 关系运算符:>、<、>=、<=、==、!=
- 逻辑运算符:&&、||、!
- 位运算符:&、|、^、~、<<、>>
- 赋值运算符:=、+=、-=、*=、/=、%=等
- 条件运算符:?:
- 逗号运算符:,
- sizeof运算符:获取大小
- 运算符优先级:使用括号明确优先级
下一章,我们将学习流程控制,了解C语言的条件语句和循环语句。
