C 语言运算符全解析:从基础用法到优先级实战指南
运算符是 C 语言的核心语法元素,贯穿数据运算、逻辑判断、赋值操作等所有场景。掌握不同类型运算符的用法、转换规则及优先级,是写出逻辑正确、高效简洁代码的关键。本文系统梳理 C 语言常用运算符、进制转换、常量定义、转义符等关联知识点,结合实操案例与避坑指南,助力快速攻克运算符难点。
一、前置基础:进制转换与常量定义
在学习运算符前,需先掌握进制表示与常量规则,这是理解位运算、数值运算的前提。
1. 程序中的进制表示与转换
C 语言支持十进制、八进制、十六进制三种常用进制,转换规则简单易懂:
-
进制表示:十进制直接书写(如 13),八进制以 0 开头(如 013),十六进制以 0x 开头(如 0x13)。
-
核心转换方法:
- 十进制转二进制:用短除法(如 13→1101);
- 八进制转二进制:三位一体(1 位八进制对应 3 位二进制,如 013→1011);
- 十六进制转二进制:四位一体(1 位十六进制对应 4 位二进制,如 0x13→00010011)。
-
应用场景:底层开发中常用十六进制表示硬件电平(如 0x99 对应二进制 10011001,代表高低电平组合)。
2. 常量:不可修改的固定值
常量分为 “值常量” 和 “常量空间”,核心规则如下:
-
值常量:直接书写的固定数据,存储在常量区(如 4、'4'、"4",分别对应整型、字符型、字符串型);
-
常量空间:用
const修饰的变量,定义时必须赋值,后续不可二次修改:const int PI = 3.1415926; PI = 10; // 报错:只读变量无法赋值 -
注意:
const修饰的是变量空间,而非值本身,本质是 “只读变量”。
二、常用转义符:控制输入输出格式
转义符用于表示无法直接输入的字符(如换行、制表符),核心常用类型如下表:
| 转义字符 | 含义 | ASCII 码(十进制) | 应用示例 | 输出效果 |
|---|---|---|---|---|
\n | 回车换行 | 10 | printf("Hello\nWorld"); | HelloWorld |
\t | 横向跳格(Tab) | 9 | printf("姓名\t年龄"); | 姓名 年龄 |
\b | 退格 | 8 | printf("abc\bd"); | abd |
\ | 输出反斜杠 | 92 | printf("\"); | \ |
' | 输出单引号 | 39 | printf('''); | ' |
" | 输出双引号 | 34 | printf(""Hello""); | "Hello" |
\ddd | 1-3 位八进制对应字符 | - | printf("\101"); | A(101 是 A 的八进制 ASCII 码) |
\xhh | 1-2 位十六进制对应字符 | - | printf("\x42"); | B(42 是 B 的十六进制 ASCII 码) |
三、数据类型转换:自动与强制转换规则
不同类型数据运算时需进行转换,分为自动转换和强制转换,直接影响运算结果准确性。
1. 自动类型转换(隐式转换)
遵循 “小类型→大类型” 原则,无需手动干预,避免数据丢失:
- 转换顺序:
char → short → int → long → float → double; - 示例:
char c = 'A'; int num = c + 10;,c先自动转为int(ASCII 码 65),再与 10 相加,结果为 75。
2. 强制类型转换(显式转换)
需手动指定转换类型,格式为(目标类型)数据,可能导致精度丢失:
- 转换规则:
long → int → short → char、double → float → int(小数转整数直接截断,不四舍五入); - 示例:
int a = (int)12.999;,结果为 12(截断小数部分);double b = (double)5 / 2;,结果为 2.5(先将 5 转为 double,避免整数除法)。 - 注意:GCC 编译器中,若转换类型与变量原有类型兼容,类型说明符可省略,但不建议省略(影响可读性)。
四、核心运算符:分类与实战用法
C 语言运算符按功能可分为 10 大类,以下是开发中最常用的核心类型,附用法、示例与注意事项:
1. 赋值运算符:=
- 功能:将右侧数据赋值给左侧变量(左侧必须是 “空间”,如变量名);
- 示例:
int a = 10; int b = a; a = b;(最终 a 和 b 均为 10); - 注意:赋值运算符是 “从右到左” 结合,如
a = b = c = 5;,先将 5 赋值给 c,再依次赋值给 b、a。
2. 算术运算符:+、-、*、/、%
-
核心规则:
/:两个int相除结果为int(截断小数),若有一个操作数为浮点型,结果为浮点型(如 5/2=2,5.0/2=2.5);%:取余运算,仅支持int类型(如 7%3=1,-7%3=-1);
-
示例:
int x = 10, y = 3; printf("%d %d %f", x/y, x%y, (float)x/y);,输出3 1 3.333333。
3. 复合运算符:+=、-=、*=、/=、%=
- 功能:简化 “变量 = 变量 运算符 数据” 的写法,等价于原表达式;
- 示例:
int a = 10; a += 2;(等价于a = a + 2,结果为 12);a *= a - 5;(等价于a = a * (a - 5),结果为 10*5=50); - 复杂案例:
a += a -= a *= a;(初始 a=10),运算顺序从右到左:先a *= a(a=100),再a -= 100(a=0),最后a += 0(a=0),输出a=0。
4. 自增自减运算符:++、--
-
核心特性:“++ 在前,先加后用;++ 在后,先用后加”;
-
示例:
int a = 10; printf("%d ", a++); // 先用后加,输出10,a变为11 printf("%d ", ++a); // 先加后用,a变为12,输出12 -
注意:同一语句中避免多次使用自增自减(如
a = a++ + ++a),不同编译器运算顺序不同,结果不确定。
5. 关系运算符:>、<、>=、<=、==、!=
- 功能:判断两个值的关系,结果为 “真(1)” 或 “假(0)”;
- 示例:
int x = 5, y = 8; printf("%d %d", x>y, x!=y);,输出0 1; - 注意:判断 “相等” 用
==,切勿误用赋值运算符=(如if(x==y)是判断,if(x=y)是赋值)。
6. 逻辑运算符:&&、||、!
-
核心规则:
- 非 0 值视为 “真”,0 视为 “假”;
&&(逻辑与):两个条件都为真才为真,第一个条件为假时,第二个条件不执行(短路特性);||(逻辑或):一个条件为真即为真,第一个条件为真时,第二个条件不执行(短路特性);!(逻辑非):真变假,假变真(如!5=0,!0=1);
-
示例:
int a=5, b=8, c=10, d=15, n=2, m=2; m = (a>b) && (n=c<<d); // a>b为假,n=c<<d不执行,m=0,n仍为2
7. 条件运算符:?:(三目运算符)
-
语法:
条件 ? 表达式1 : 表达式2(条件为真执行表达式 1,否则执行表达式 2); -
示例:
int x=10, y=9; int a = --x == y++ ? --x : ++y; // 步骤:--x=9,y++=9(y变为10),9==9为真,执行--x=8,a=8 int b = x++; // x=8先用后加,b=8,x变为9 int c = y; // y=10,c=10 printf("a=%d b=%d c=%d", a, b, c); // 输出a=8 b=8 c=10
8. sizeof 运算符:获取数据类型 / 变量的空间大小
-
语法:
sizeof(数据类型)或sizeof(变量),返回值为无符号整数; -
示例:
printf("int=%zu\n", sizeof(int)); // 输出4(32位系统) int a=10; printf("a=%zu\n", sizeof(a)); // 输出4 -
注意:
sizeof是运算符而非函数,括号可省略(如sizeof int),但变量名括号不可省略(如sizeof a)。
9. 逗号运算符:,
-
功能:分隔多个表达式,按从左到右顺序执行,最终结果为最后一个表达式的值;
-
示例:
int a=0, b=0, c=0; a = (12, 13, 15); // 执行12、13,最终a=15 printf("a=%d\tb=%d\tc=%d", a, b, c); // 输出a=15 b=0 c=0 -
注意:赋值运算符优先级高于逗号运算符,需加括号明确运算范围,否则结果异常。
10. 位运算符:直接操作二进制位(&、|、~、^、<<、>>)
位运算符直接操作变量的二进制位,常用于底层开发、性能优化,核心用法如下:
| 运算符 | 含义 | 规则 | 示例(14 的二进制为 00001110) | 结果(二进制) | 十进制结果 | ||
|---|---|---|---|---|---|---|---|
& | 按位与 | 全 1 为 1,否则为 0 | 14 & 17(00010001) | 00000000 | 0 | ||
| ` | ` | 按位或 | 全 0 为 0,否则为 1 | 14 | 17 | 00011111 | 31 |
~ | 按位取反 | 0 变 1,1 变 0 | ~14(unsigned char) | 11110001 | 241 | ||
^ | 按位异或 | 相同为 0,不同为 1 | 14 ^ 17 | 00011111 | 31 | ||
<< | 按位左移 | 左移 n 位 = 原数 ×2ⁿ | 14 << 2 | 00111000 | 56 | ||
>> | 按位右移 | 右移 n 位 = 原数 ÷2ⁿ(取商) | 14 >> 2 | 00000111 | 3 |
五、运算符优先级与结合性(必记)
运算符优先级决定运算顺序,优先级越高越先执行;结合性决定同一优先级运算符的执行方向,核心规则如下:
1. 核心优先级排序(从高到低)
- 初等运算符:
()、[]、->、.(最高); - 单目运算符:
!、~、++、--、&、sizeof; - 算术运算符:
*、/、%>+、-; - 移位运算符:
<<、>>; - 关系运算符:
<、<=、>、>=>==、!=; - 位运算符:
&>^>|; - 逻辑运算符:
&&>||; - 条件运算符:
?:; - 赋值运算符:
=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|=; - 逗号运算符:
,(最低)。
2. 关键总结
- 括号
()可改变优先级,复杂表达式建议加括号(如a + b * c等价于a + (b * c),但(a + b) * c优先级更高); - 赋值运算符、条件运算符是 “从右到左” 结合,其余多数运算符是 “从左到右” 结合;
- 记忆口诀:“括号最高,单目第二,算术移位关系,位与逻辑条件,赋值最低逗号尾”。
六、常见踩坑点与避坑指南
- 优先级混淆:误将
==与=混用,或忽略&&优先级高于||(如x>0 || x<10 && x!=5等价于x>0 || (x<10 && x!=5)); - 自增自减滥用:同一语句多次使用
++/--(如a = ++a + a--),导致结果不确定; - 整数除法陷阱:
int类型相除忽略小数,需显式转换为浮点型(如(float)5/2而非5/2); - 逻辑运算符短路特性:依赖
&&/||的第二个条件执行(如if(x!=0 && y/x>5),x=0 时 y/x 不执行,避免除零错误); - 位运算符误用:将
&(按位与)与&&(逻辑与)、|(按位或)与||(逻辑或)混淆(如if(x&1)判断奇数,if(x&&1)判断 x 非 0)。