在C语言中,除了常见的赋值、条件、位运算外,逗号运算符、sizeof运算符以及()、[]等最高优先级运算符虽不常被重点提及,但在实际开发和面试中频繁出现。
一、逗号运算符
逗号运算符(,)是C语言中优先级最低的运算符,作用是将多个表达式组合成一个
1.1 核心特性
- 执行顺序:从左到右依次执行每个表达式(左侧表达式仅执行,结果丢弃);
- 返回值:最终结果为最后一个表达式的值;
- 优先级:所有运算符中最低,必须通过括号明确作用范围;
- 适用场景:for循环中合并多个操作、赋值语句中组合多步计算。
1.2 基本用法示例
int a = (1, 2, 3, 4, 5);
printf("a = (1, 2, 3, 4, 5) → a = %d\n", a);
int b, c, d;
b = (c = 10, d = 20, c + d);// 先执行c=10,再执行d=20,最终返回c+d
printf("b = (c = 10, d = 20, c + d) → b=%d, c=%d, d=%d\n", b, c, d);
return 0;
1.3 与for循环的结合(高频场景)
逗号运算符最常用在for循环中,将初始化、递增/递减操作合并为一行,简化代码:
#include <stdio.h>
int main() {
printf("=== 逗号运算符与for循环结合 ===\n");
int i, j;
for (i = 0, j = 10; i < 5; i++, j--) {
printf("i=%d, j=%d\n", i, j);
}
// 输出结果:
// i=0, j=10
// i=1, j=9
// i=2, j=8
// i=3, j=7
// i=4, j=6
return 0;
}
1.4 经典面试题解析(避坑重点)
逗号运算符的核心坑点是优先级低于赋值运算符,以下4道面试题覆盖所有高频场景:
int a, b;
a = 1, 2, 3; // 等价于 (a=1), 2, 3 → 赋值优先级高于逗号
b = (1, 2, 3); // 括号提升逗号运算符优先级,返回最后一个表达式
printf("a = 1, 2, 3 → a = %d\n", a); // 输出:1
printf("b = (1, 2, 3) → b = %d\n", b); // 输出:3
int x = 5, y = 10;
// 逗号分隔多个赋值,最终判断x+y>0(恒成立)
if (x = 1, y = 2, x + y > 0) {
printf("if条件成立: x=%d, y=%d\n", x, y); // 输出:x=1, y=2
}
// 逗号分隔多个printf,最终返回100作为函数参数
printf("函数调用结果: %d\n", (printf("Hello, "), printf("World! "), 100));
// 输出:Hello, World! 函数调用结果: 100
// 注意:()内是逗号运算符,不是初始化列表!每个元素仅取最后一个值
int arr[3][4] = {(1,2,3,4), (5,6,7,8), (9,10,11,12)};
// 等价于:arr[3][4] = {4, 8, 12, 0, ...}(其余元素默认初始化0)
printf("arr[0][1] = %d, arr[1][1] = %d, arr[2][1] = %d\n",
arr[0][1], arr[1][1], arr[2][1]); // 输出:0 0 0
return 0;
//二维数组初始化时,`()`会将内部变为逗号表达式,而非多个元素。若需正确初始化,应使用`{1,2,3,4}`(无括号)或`{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}`。
}
二、sizeof
sizeof是C语言中的单目运算符(不是函数),用于计算数据类型、变量或表达式占用的内存字节数,编译时求值,不执行表达式。
2.1 核心特性
- 本质:运算符,而非函数,可省略括号(类型名除外);
- 求值时机:编译期计算,表达式仅判断类型,不实际执行;
- 关键区别:数组作为函数参数时会退化为指针,
sizeof返回指针大小; - 常见用途:计算数组元素个数、跨平台代码中确保类型大小兼容性。
2.2 基本用法示例
#include <stdio.h>
int main() {
printf("=== sizeof运算符基本用法 ===\n");
int a = 10;
// 变量可省略括号,类型名必须加括号
printf("sizeof(a) = %zu\n", sizeof(a)); // 输出:4(int默认4字节)
printf("sizeof a = %zu\n", sizeof a); // 输出:4(合法,无括号)
printf("sizeof(int) = %zu\n", sizeof(int)); // 输出:4
// 关键特性:编译时求值,不执行表达式
int b = 0;
printf("sizeof(b = 100) = %zu\n", sizeof(b = 100)); // 输出:4(仅判断int类型)
printf("b的值仍然是: %d\n", b); // 输出:0(b=100不执行)
return 0;
}
2.3 不同数据类型的sizeof结果
#include <stdio.h>
int main() {
printf("=== sizeof与各种数据类型 ===\n");
// 基本数据类型(结果因平台而异,以下为64位系统示例)
printf("char: %zu bytes\n", sizeof(char)); // 1
printf("short: %zu bytes\n", sizeof(short)); // 2
printf("int: %zu bytes\n", sizeof(int)); // 4
printf("long: %zu bytes\n", sizeof(long)); // 8(64位系统)
printf("float: %zu bytes\n", sizeof(float)); // 4
printf("double: %zu bytes\n", sizeof(double)); // 8
// 指针类型(所有指针大小相同,取决于系统位数)一般在32位系统中为4,64位为8
printf("char*: %zu bytes\n", sizeof(char*)); // 8(64位系统)
printf("int*: %zu bytes\n", sizeof(int*)); // 8
printf("double*: %zu bytes\n", sizeof(double*)); // 8
return 0;
}
2.4 sizeof与数组的关键细节
数组在函数内外的sizeof结果不同,字符串数组与字符串指针的sizeof差异也是面试热点:
#include <stdio.h>
#include <string.h>
// 数组作为函数参数退化为指针
void testArray(int arr[]) {
printf("函数内sizeof(arr): %zu\n", sizeof(arr)); // 输出:8(指针大小)
}
int main() {
printf("=== sizeof与数组 ===\n");
// 1. 普通数组:函数外sizeof返回整个数组大小
int arr[10];
printf("函数外sizeof(arr): %zu\n", sizeof(arr)); // 输出:40(10*4)
printf("数组元素个数: %zu\n", sizeof(arr) / sizeof(arr[0])); // 输出:10(通用计算方式)
// 函数调用验证数组退化
testArray(arr);
// 2. 字符串数组 vs 字符串指针
char str[] = "Hello"; // 字符串数组,包含'\0'
char* pstr = "Hello"; // 字符串指针,指向常量区
printf("\n字符串相关sizeof对比:\n");
printf("sizeof(str) = %zu\n", sizeof(str)); // 输出:6(H e l l o \0)
printf("sizeof(pstr) = %zu\n", sizeof(pstr)); // 输出:8(指针大小)
// 与strlen的区别(strlen计算有效字符数,不含'\0')
printf("strlen(str) = %zu\n", strlen(str)); // 输出:5
printf("strlen(pstr) = %zu\n", strlen(pstr)); // 输出:5
return 0;
}
2.5 sizeof与strlen的区别
| 特性 | sizeof | strlen |
|---|---|---|
| 类型 | 编译时运算符 | 运行时函数 |
| 作用 | 计算内存占用字节数 | 计算字符串有效长度 |
处理\0 | 包含空字符(计入大小) | 遇到\0停止(不计入) |
| 数组 | 返回整个数组大小 | 返回字符串实际字符数 |
| 指针 | 返回指针本身大小 | 计算指针指向的字符串长度 |
三、最高优先级运算符:()[]->.
C语言中优先级最高的四类运算符是()、[]、->、.,它们的优先级高于所有算术、赋值运算符,核心用于“访问数据”或“改变运算规则”。
3.1 四类运算符的作用
| 运算符 | 名称 | 核心用途 |
|---|---|---|
() | 括号运算符 | 改变优先级、类型转换、函数调用、宏定义 |
[] | 数组下标运算符 | 访问数组元素(arr[i]等价于*(arr+i)) |
. | 结构体成员运算符 | 结构体变量访问成员 |
-> | 结构体指针成员运算符 | 结构体指针访问成员(ps->age等价于(*ps).age) |
3.2 基本用法示例
// 定义结构体
struct Student {
char name[20];
int age;
};
int main() {
printf("=== 最高优先级运算符基本用法 ===\n");
// 1. 括号运算符 ():改变优先级
int a = (2 + 3) * 4;
printf("(2 + 3) * 4 = %d\n", a); // 输出:20(优先计算括号内)
// 2. 数组下标运算符 []
int arr[5] = {1, 2, 3, 4, 5};
printf("arr[2] = %d\n", arr[2]); // 输出:3(访问第3个元素)
// 3. 结构体成员访问 . 和 ->
struct Student s = {"张三", 20}; // 结构体变量
struct Student *ps = &s; // 结构体指针
printf("学生姓名: %s\n", s.name); // 变量用.访问
printf("学生年龄: %d\n", ps->age); // 指针用->访问
return 0;
}
3.3 括号运算符的4大核心用途
#include <stdio.h>
#define SQUARE(x) ((x) * (x)
int main() {
printf("=== 括号运算符的多种用途 ===\n");
// 用途1:改变运算优先级
int a = 2 + 3 * 4; // 14(默认先乘后加)
int b = (2 + 3) * 4; // 20(括号改变顺序)
printf("2 + 3 * 4 = %d\n", a);
printf("(2 + 3) * 4 = %d\n", b);
// 用途2:类型转换
double result = (double)5 / 2; // 强制转换为double,避免整数除法
printf("(double)5 / 2 = %.1f\n", result); // 输出:2.5
// 用途3:复合表达式(与条件运算符结合)
int x = 5, y = 10;
int max = (x > y) ? x : y; // 括号提升可读性
printf("%d和%d中较大的是: %d\n", x, y, max); // 输出:10
// 用途4:函数式宏定义(双重括号避免陷阱)
printf("SQUARE(3+2) = %d\n", SQUARE(3+2)); // 输出:25(等价于(3+2)*(3+2))
// 若宏定义为(x*x),则会变成3+2*3+2=11,双重括号是关键!
return 0;
}
四、总结与避坑指南
- 逗号运算符:优先级最低,必须加括号;返回最后一个表达式值,避免在数组初始化中误用。
- sizeof运算符:编译时求值,不执行表达式;数组作为函数参数退化为指针,字符串数组与指针的
sizeof结果不同。 - 最高优先级运算符:
()可改变优先级、类型转换;[]访问数组;.和->访问结构体成员,优先级最高无需括号。
4万+

被折叠的 条评论
为什么被折叠?



