什么是表达式?
凡是能求出一个值的东西,就是表达式。
C 语言中,表达式是最基本的"值的生产单元"。表达式可以简单到只有一个数字 5,也可以复杂到嵌套多层函数调用和运算。
核心规律:不管哪种表达式,最终都能求出一个值。 这就是表达式的本质。
C 语言中的表达式类型
1.字面量表达式
直接写一个常量值,它本身就是表达式。
cpp5 // 整数字面量表达式,值是 5 3.14 // 浮点字面量表达式,值是 3.14 'a' // 字符字面量表达式,值是 97(ASCII码) "hello" // 字符串字面量表达式,值是字符串首地址
使用场景: 赋值、传参、参与运算。
cpp
int x = 5; // 5 是表达式,值赋给 x
printf("%d", 100); // 100 是表达式,作为参数传递
int y = 5 + 3.14; // 5 和 3.14 都是表达式
2.标识符表达式
变量名、函数名本身就是表达式。
cppint x = 10; x // 标识符表达式,值是 10 int *ptr = &x; ptr // 标识符表达式,值是 x 的地址
使用场景: 赋值右边、传参、参与运算。
cppint a = 5; int b = a; // a 是标识符表达式,值 5 赋给 b print_array(a); // a 是标识符表达式,作为参数传递 int c = a + 3; // a 是标识符表达式,参与算术运算
3.算术表达式
用算术运算符(+ - * / %)连接操作数。
cppa + b // 值是 a 加 b a * 2 // 值是 a 乘以 2 a % 3 // 值是 a 除以 3 的余数 -a // 值是 a 的相反数
使用场景: 计算、赋值、传参。
cppint sum = a + b; // 算术表达式的值赋给 sum printf("%d", a * 2); // 算术表达式的值作为参数 int result = (a + b) * (c - d); // 复杂算术表达式
4.关系表达式
用关系运算符(> < >= <= == !=)比较两个值,结果是 0(假)或 1(真)。
cppa > b // a 大于 b 则为 1,否则为 0 a == 5 // a 等于 5 则为 1,否则为 0 a != b // a 不等于 b 则为 1,否则为 0
使用场景: 条件判断、循环条件、赋值。
cppif (a > b) { // 关系表达式作为 if 条件 // ... } while (i < 10) { // 关系表达式作为循环条件 i++; } int flag = (a == 5); // 关系表达式的值赋给变量
5.逻辑表达式
用逻辑运算符(&& || !)组合条件,结果是 0(假)或 1(真)。
cppa > 0 && b > 0 // a 和 b 都大于 0 则为 1 a > 0 || b > 0 // a 或 b 有一个大于 0 则为 1 !a // a 为 0 则为 1,a 非 0 则为 0
使用场景: 复合条件判断。
cppif (age >= 18 && has_id) { // 两个条件同时满足 printf("可以进入"); } if (score > 90 || is_bonus) { // 满足任一条件 printf("优秀"); } if (!is_error) { // 取反 printf("没有错误"); }
6.条件表达式(三目运算符)
格式:条件 ? 值1 : 值2。条件为真取值1,为假取值2。
cppa > b ? a : b // 如果 a > b,值是 a;否则值是 b
使用场景: 简洁地做二选一赋值
cppint max = (a > b) ? a : b; // 取 a 和 b 中较大的 printf("%s", score >= 60 ? "及格" : "不及格"); // 条件输出 int abs_val = (x >= 0) ? x : -x; // 求绝对值
7.赋值表达式
用赋值运算符(= += -= *= /=)给变量赋值。赋值表达式本身也有值,值就是赋给变量的那个数。
cppx = 10 // 表达式的值是 10 x += 5 // 等价于 x = x + 5,表达式的值是 x 的新值 x *= 2 // 等价于 x = x * 2,表达式的值是 x 的新值
使用场景: 赋值、链式赋值、在条件中使用。
cppint x = 10; // 赋值表达式 int a, b, c; a = b = c = 5; // 链式赋值:c=5 值为5,b=5 值为5,a=5 if ((x = get_value()) > 0) { // 赋值表达式的值参与比较 // x 被赋值,同时判断是否大于 0 }
8.逗号表达式
用逗号 , 连接多个表达式,从左到右依次执行,整个表达式的值是最后一个表达式的值。
cppa = 1, b = 2, c = 3 // 依次执行,整个表达式的值是 3
使用场景: for 循环中初始化或更新多个变量。
cppfor (int i = 0, j = 10; i < j; i++, j--) { // i++ 和 j-- 组成逗号表达式 } int result = (a = 5, b = 10, a + b); // result = 15
9.函数调用表达式
函数调用表达式的格式是:函数名(参数列表)。
它的含义是:调用一个函数,并产生一个值------这个值就是函数的返回值。
所以函数调用表达式本身是有"值"的,它的值就是函数 return 回来的那个东西。
cppprintf("hello") // 值是 printf 的返回值(打印的字符数) print_array(arr) // 值是 print_array(arr) 的返回值函数调用表达式既是一个"动作"(调用函数),也是一个"值"(函数的返回值)。 这就是为什么它可以出现在赋值、运算、条件判断等各种位置。
print_array(arr) 函数调用表达式的详解
print_array 是函数名
arr 是参数(实参)
整个 print_array(arr) 是一个函数调用表达式
print_array 函数的"值"是什么?取决于 print_array 函数的返回值:
❶ print_array 函数调用表达式的值是空的(没有值) ,返回类型是 void,
cppvoid print_array(int arr[]) { // 没有 return 值 }❷ print_array 函数调用表达式有返回值,赋值给变量result
cppint print_array(int arr[]) { return 100; } int result = print_array(arr); // print_array(arr) 这个函数调用表达式的值就是 100
print_array(arr)函数调用表达式的不同使用场景
场景一:print_array(arr)作为独立语句
函数调用表达式单独成一行,不接收返回值。常见于 void 函数,调用目的不是为了取值,而是为了执行函数的副作用(比如打印、修改数据)。
cppprint_array(arr);
场景二:print_array(arr)赋值给变量
print_array(arr)函数调用表达式的值(返回值)赋给一个变量。这是最常见的用法------调用函数,拿到结果,存起来。
cppint result = print_array(arr); // 返回值赋给变量result
场景三:print_array(arr)为另一个表达式的操作数
print_array(arr) 是一个函数调用表达式,它的值参与算术运算。print_array(arr)函数调用表达式的值可以像普通数值一样参与计算。
cppint total = print_array(arr) + 10; // 返回值参与运算
场景四:print_array(arr)作为另一个函数参数(嵌套调用)
print_array(arr) 是函数调用表达式,它的返回值作为 printf 的参数传递。print_array函数调用表达式可以嵌套在另一个函数调用中。
cpp//print_array(arr) 返回值作为printf函数的参数 printf("%d", print_array(arr));
场景五:print_array(arr)用在条件判断中
print_array(arr) 是函数调用表达式,print_array(arr)的返回值(通常是 0假 或 1真)作为if判断条件判断的依据。
cppif (is_valid(arr)) { ... }else{ ... }
场景六:print_array(arr)用在循环条件中
print_array(arr)是函数调用表达式,每次循环都会调用一次,根据print_array(arr)返回值(通常是 0假 或 1真)决定是否继续循环。
cppwhile ( print_array(arr)) ) { // ... }
10.sizeof 表达式
格式:sizeof(类型或表达式)。值是占用字节数,类型是 size_t(无符号整数)。
cppsizeof(int) // 值是 4(通常) sizeof(arr) // 值是 20(5×4),arr 不退化 sizeof(x) // 值是变量 x 占的字节数
使用场景: 动态内存分配、数组长度计算。
cppint arr[5]; int len = sizeof(arr) / sizeof(arr[0]); // 计算数组元素个数,值为 5 int *p = malloc(10 * sizeof(int)); // 分配 10 个 int 的空间
11.指针相关表达式
包括取地址 &、解引用 *、指针运算。
cpp&x // 取地址表达式,值是 x 的内存地址 *ptr // 解引用表达式,值是 ptr 指向的那个数据内容数值 ptr + 1 // 指针算术表达式,值是下一个元素的内存地址
使用场景: 动态内存操作、数组遍历、函数间传递地址
cppint x = 10; int *ptr = &x; // &x 是取内存地址表达式 int val = *ptr; // *ptr 是解引用表达式,值为 *ptr=数据内容值10 int arr[5] = {1,2,3,4,5}; int *p = arr + 2; // arr + 2指针算术表达式,arr + 2是内存地址 p 指向 arr[2] int v = *(arr + 3); // 解引用表达式,值为 arr[3] 即 4
12.强制类型转换表达式
格式:(类型)表达式。值是将原值转换为目标类型后的结果值
cpp(int)3.14 // 值是 3 (float)x // 值是 x 转换为浮点数
使用场景: 类型不匹配时的显式转换。
cppint x = (int)3.14; // 浮点转整数,值为 3 float ratio = (float)a / b; // 避免整数除法截断