C 语言运算符全解析:从基础用法到优先级实战指南

66 阅读9分钟

C 语言运算符全解析:从基础用法到优先级实战指南

运算符是 C 语言的核心语法元素,贯穿数据运算、逻辑判断、赋值操作等所有场景。掌握不同类型运算符的用法、转换规则及优先级,是写出逻辑正确、高效简洁代码的关键。本文系统梳理 C 语言常用运算符、进制转换、常量定义、转义符等关联知识点,结合实操案例与避坑指南,助力快速攻克运算符难点。

一、前置基础:进制转换与常量定义

在学习运算符前,需先掌握进制表示与常量规则,这是理解位运算、数值运算的前提。

1. 程序中的进制表示与转换

C 语言支持十进制、八进制、十六进制三种常用进制,转换规则简单易懂:

  • 进制表示:十进制直接书写(如 13),八进制以 0 开头(如 013),十六进制以 0x 开头(如 0x13)。

  • 核心转换方法

    1. 十进制转二进制:用短除法(如 13→1101);
    2. 八进制转二进制:三位一体(1 位八进制对应 3 位二进制,如 013→1011);
    3. 十六进制转二进制:四位一体(1 位十六进制对应 4 位二进制,如 0x13→00010011)。
  • 应用场景:底层开发中常用十六进制表示硬件电平(如 0x99 对应二进制 10011001,代表高低电平组合)。

2. 常量:不可修改的固定值

常量分为 “值常量” 和 “常量空间”,核心规则如下:

  • 值常量:直接书写的固定数据,存储在常量区(如 4、'4'、"4",分别对应整型、字符型、字符串型);

  • 常量空间:用const修饰的变量,定义时必须赋值,后续不可二次修改:

    const int PI = 3.1415926;
    PI = 10; // 报错:只读变量无法赋值
    
  • 注意:const修饰的是变量空间,而非值本身,本质是 “只读变量”。

二、常用转义符:控制输入输出格式

转义符用于表示无法直接输入的字符(如换行、制表符),核心常用类型如下表:

转义字符含义ASCII 码(十进制)应用示例输出效果
\n回车换行10printf("Hello\nWorld");HelloWorld
\t横向跳格(Tab)9printf("姓名\t年龄");姓名 年龄
\b退格8printf("abc\bd");abd
\输出反斜杠92printf("\");\
'输出单引号39printf(''');'
"输出双引号34printf(""Hello"");"Hello"
\ddd1-3 位八进制对应字符-printf("\101");A(101 是 A 的八进制 ASCII 码)
\xhh1-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 → chardouble → 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. 算术运算符:+、-、*、/、%

  • 核心规则:

    1. /:两个int相除结果为int(截断小数),若有一个操作数为浮点型,结果为浮点型(如 5/2=2,5.0/2=2.5);
    2. %:取余运算,仅支持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. 逻辑运算符:&&、||、!

  • 核心规则:

    1. 非 0 值视为 “真”,0 视为 “假”;
    2. &&(逻辑与):两个条件都为真才为真,第一个条件为假时,第二个条件不执行(短路特性);
    3. ||(逻辑或):一个条件为真即为真,第一个条件为真时,第二个条件不执行(短路特性);
    4. !(逻辑非):真变假,假变真(如!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=8a=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); // 执行1213,最终a=15
    printf("a=%d\tb=%d\tc=%d", a, b, c); // 输出a=15 b=0 c=0
    
  • 注意:赋值运算符优先级高于逗号运算符,需加括号明确运算范围,否则结果异常。

10. 位运算符:直接操作二进制位(&、|、~、^、<<、>>

位运算符直接操作变量的二进制位,常用于底层开发、性能优化,核心用法如下:

运算符含义规则示例(14 的二进制为 00001110)结果(二进制)十进制结果
&按位与全 1 为 1,否则为 014 & 17(00010001)000000000
``按位或全 0 为 0,否则为 114170001111131
~按位取反0 变 1,1 变 0~14(unsigned char)11110001241
^按位异或相同为 0,不同为 114 ^ 170001111131
<<按位左移左移 n 位 = 原数 ×2ⁿ14 << 20011100056
>>按位右移右移 n 位 = 原数 ÷2ⁿ(取商)14 >> 2000001113

五、运算符优先级与结合性(必记)

运算符优先级决定运算顺序,优先级越高越先执行;结合性决定同一优先级运算符的执行方向,核心规则如下:

1. 核心优先级排序(从高到低)

  1. 初等运算符:()[]->.(最高);
  2. 单目运算符:!、~、++、--、&、sizeof
  3. 算术运算符:*、/、% > +、-
  4. 移位运算符:<<、>>
  5. 关系运算符:<、<=、>、>= > ==、!=
  6. 位运算符:& > ^ > |
  7. 逻辑运算符:&& > ||
  8. 条件运算符:?:
  9. 赋值运算符:=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|=
  10. 逗号运算符:(最低)。

2. 关键总结

  • 括号()可改变优先级,复杂表达式建议加括号(如a + b * c等价于a + (b * c),但(a + b) * c优先级更高);
  • 赋值运算符、条件运算符是 “从右到左” 结合,其余多数运算符是 “从左到右” 结合;
  • 记忆口诀:“括号最高,单目第二,算术移位关系,位与逻辑条件,赋值最低逗号尾”。

六、常见踩坑点与避坑指南

  1. 优先级混淆:误将===混用,或忽略&&优先级高于||(如x>0 || x<10 && x!=5等价于x>0 || (x<10 && x!=5));
  2. 自增自减滥用:同一语句多次使用++/--(如a = ++a + a--),导致结果不确定;
  3. 整数除法陷阱int类型相除忽略小数,需显式转换为浮点型(如(float)5/2而非5/2);
  4. 逻辑运算符短路特性:依赖&&/||的第二个条件执行(如if(x!=0 && y/x>5),x=0 时 y/x 不执行,避免除零错误);
  5. 位运算符误用:将&(按位与)与&&(逻辑与)、|(按位或)与||(逻辑或)混淆(如if(x&1)判断奇数,if(x&&1)判断 x 非 0)。