7. 数据的操盘手:运算符大全

变量把数据存起来,输入输出让数据流起来。但程序真正干活的部分,是把存进来的数据拿去做运算——加减乘除、比较大小、判断真假、甚至摆弄二进制位。这些动作,全都靠运算符来完成。

运算符就是 C 语言里的“操盘手”:它们决定数据怎么变,关系怎么判,逻辑怎么走。今天这篇文章,我们就一次把 C 语言常用的运算符认全。不用担心记不住,你可以把它当作“速查手册”,用到的时候回来看一看就行。


一、算术运算符:最基本的加减乘除

C 语言提供了五种基本算术运算符:

运算符含义示例结果(假设 a=10, b=3)
+加法a + b13
-减法a - b7
*乘法a * b30
/除法a / b3(注意!)
%取模(求余数)a % b1

最需要注意的就是除法 /

两个整数相除,结果一定是整数,小数部分直接丢弃(不是四舍五入)。所以 10 / 3 得到 35 / 6 得到 0。要想得到小数结果,至少让其中一个操作数变成浮点数:

int a = 10, b = 3;
printf("%d\n", a / b);           // 3
printf("%f\n", 10.0 / 3);        // 3.333333
printf("%f\n", (double)a / b);   // 3.333333

取模运算符 % 只能用于整数(C99 之前要求整数),结果是相除后的余数。取模的符号与被除数相同:-10 % 3 结果是 -1

另外,C 语言没有幂运算符(^ 不是幂,是位运算),计算次方要用库函数 pow(在 <math.h> 里)。


二、赋值与复合赋值:让等号更强大

赋值运算符就是等号 =。它的意思是“把右边表达式的值,放进左边的变量里”。

int x;
x = 5 + 3;   // x 变成 8

注意,等号不是数学里的“相等”,而是“赋予”。你可以连续赋值:

int a, b, c;
a = b = c = 0;  // 从右往左,三个变量都变成 0

为了写起来更简洁,C 还提供了复合赋值运算符。它们把运算和赋值合二为一:

运算符等价于
x += 5x = x + 5
x -= 5x = x - 5
x *= 5x = x * 5
x /= 5x = x / 5
x %= 5x = x % 5

后面的位运算也有对应的复合赋值(如 &=|=^= 等)。这些写法不光是少敲几个字,有时也能让编译器生成更高效的代码(特别是对早期编译器而言)。


三、自增自减:++--

++ 让变量加 1,-- 让变量减 1。它们既可以放在变量前面(前缀),也可以放在后面(后缀),但行为有微妙差别。

  • 前缀:先加/减,再使用变量的值。
  • 后缀:先使用变量的当前值,再加/减。

看例子:

int a = 5, b;
b = ++a;   // 先 a 变成 6,再赋给 b,所以 b=6, a=6
int a = 5, b;
b = a++;   // 先 b 取 a 的值 5,再 a 变成 6,所以 b=5, a=6

如果单独写一行 a++;++a;,效果一样。区别只在它们和“取值”动作合并在一个表达式里时才显现。

避坑指南:不要在一个表达式里多次修改同一个变量并取值,比如 c = a++ + ++a;,这种代码的结果是未定义的,不同编译器可能得出不同结果,绝不要这样写。


四、关系运算符:比大小,判真假

关系运算符用来比较两个值,结果是 1(真)或 0(假)。C 语言里没有真正的“布尔”类型(C99 有 _Bool,后面会提到),真假直接用整数表示。

运算符含义示例(a=5, b=3)结果
==等于a == b0
!=不等于a != b1
>大于a > b1
<小于a < b0
>=大于等于a >= 51
<=小于等于a <= 40

最常见的错误就是把相等写成 =(赋值)。if (a = 5) 永远为真,因为赋值表达式的值就是 5(非零即真),这会导致极难发现的逻辑 bug。比较相等务必用双等号 ==


五、逻辑运算符:拼装条件

逻辑运算符用来连接多个关系表达式,构造复杂的判断条件。

运算符含义示例结果
&&逻辑与(并且)(a > 2) && (b < 10)两边都真才为真
``逻辑或(或者)
!逻辑非(取反)!(a > 2)真变假,假变真

逻辑运算符有一个非常重要的特性——短路求值

  • 对于 A && B,如果 A 已经是假,B 根本就不会计算。
  • 对于 A || B,如果 A 已经是真,B 同样不会计算。

这个特性常常被用来安全地编写代码,比如:

int *p = NULL;
if (p != NULL && *p == 10) {  // p 为空时不会去读 *p,避免了崩溃
    printf("ok\n");
}

逻辑非 ! 可以把非零值变成 0,0 变成 1。!5 的结果是 0。


六、位运算符初探:直接玩转二进制

位运算符是对数据的二进制位进行操作的。它们是 C 语言高效和贴近硬件的体现,在嵌入式、系统编程和性能敏感的场景里非常有用。我们暂时只做感性了解,后面会有专门的文章深入。

运算符含义示例(a=5即0101,b=3即0011)结果
&按位与a & b (0101 & 0011)1 (0001)
``按位或`a
^按位异或a ^ b6 (0110)
~按位取反~a取决于位数,对于8位是 11111010
<<左移a << 110 (1010)
>>右移a >> 12 (0010)
  • &:两位都是 1 结果才为 1,常用来“屏蔽”某些位。
  • |:任一位是 1 结果就为 1,用来“置位”。
  • 异或 ^:两位不同为 1,相同为 0,用于切换位或简单加密。
  • 取反 ~:所有位翻转,0 变 1,1 变 0。
  • 移位<< 左移一位相当于乘 2,>> 右移一位相当于除 2(对正整数来说)。

注意:位运算符操作的是整型,不要弄混 &&&|||,它们是完全不同的东西。


七、其他你可能遇到的运算符

1. 条件运算符(三目运算符)

条件 ? 表达式1 : 表达式2 :如果条件为真,计算并返回表达式1,否则返回表达式2。

int max = (a > b) ? a : b;

它相当于 if-else 的简写形式,适合简单的二选一赋值。

2. 逗号运算符

, 可以连接多个表达式,整个表达式的值是最后一个表达式的值。它主要在 for 循环里用(后面会见到):

int x, y;
x = (y = 3, y + 2);  // y 被赋为 3,然后 x 得到 5

日常写代码尽量不要滥用它,会让可读性变差。

3. sizeof 运算符

我们之前已经见过,用来获取类型或变量的大小,编译时计算。它也是运算符,不是函数。


八、运算符优先级与结合性速查

当你在一行里写多个运算符时,谁先算谁后算?规则就是优先级。如果优先级相同,结合性决定从左往右还是从右往左。

一个典型例子:a + b * c 先算 * 再算 +,因为乘除优先级高于加减。

优先级简表(从高到低,同一行优先级相同):

优先级运算符结合性
1() [] . ->左到右
2! ~ ++ -- +(正) -(负) *(解引用) &(取地址) (类型) sizeof右到左
3* / %左到右
4+ -左到右
5<< >>左到右
6< <= > >=左到右
7== !=左到右
8& (按位与)左到右
9^左到右
10``
11&&左到右
12`
13?:右到左
14= += -=右到左
15,左到右

不用死记硬背,建议多用括号。括号的优先级最高,而且能让意图一目了然,比依赖默认优先级安全得多。


九、常见陷阱集合

  1. 整数除法截断
    double half = 1 / 2;half 是 0.0。应改为 1.0 / 2 或强制类型转换。

  2. == 写成 =
    if (a = 5) 恒为真。可以把常量写在左边:if (5 == a),这样如果漏写一个 = 会编译错误。

  3. 自增的副作用
    int x = a++ + ++a; 是未定义行为,不同编译器结果不同,绝不要写。

  4. 位运算与逻辑运算混淆
    &&&||| 绝不等价。if (a & b) 是按位与,如果 a 和 b 是 0 或 1 可能碰巧对,但多数情况下语义错误。

  5. 对浮点数用 %
    3.14 % 2 非法,取模只能用于整数。

  6. 优先级导致意外
    *p++*(p++) 而不是 (*p)++,因为后缀 ++ 优先级高于解引用 *。同样,多用括号避免这类头疼问题。


十、小结

今天一口气认识了算术、赋值、自增自减、关系、逻辑、位运算、条件、逗号等 C 语言运算符,了解了优先级和结合性的基本规则。这些运算符就是程序的“动词”,它们决定了数据如何被操纵、条件如何判断、逻辑如何组织。

下一步,我们要用这些运算符来指挥程序的走向——分支结构来了。ifelseswitch,让代码在不同条件下走不同的路,程序从此有了“判断力”。


课后小练习

  1. 写程序输入一个三位整数(比如 367),输出它的个位、十位、百位数字。提示:善用 /%
  2. 声明两个变量 a=10, b=20,通过加减法和异或运算两种方法,在不使用第三个变量的情况下交换它们的值,并打印交换前后的结果。
  3. 用条件运算符 ?: 实现:输入一个整数,输出它的绝对值。
  4. 试试写一行代码:int x = 5; printf("%d\n", x++ + ++x); 用不同编译器试试看结果是否一致?再决定永远不要写这样的代码。

我们下期见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值