C 运算符

运算符是 C 用来操作数据的符号。C 的运算符极其丰富——不仅有算术、关系、逻辑,还有强大的位运算(直接操作二进制位),这也是 C 接近硬件的体现之一。本篇系统过一遍 C 的所有运算符。

一、算术运算符

最基础的运算符,用于数学计算:

#include <stdio.h>

int main(void) {
    int a = 17, b = 5;

    // 基本算术
    printf("%d + %d = %d\n", a, b, a + b);   // 22
    printf("%d - %d = %d\n", a, b, a - b);   // 12
    printf("%d * %d = %d\n", a, b, a * b);   // 85
    printf("%d / %d = %d\n", a, b, a / b);   // 3(整数除法,丢小数!)
    printf("%d %% %d = %d\n", a, b, a % b);  // 2(取余,只对整数)

    // 浮点除法
    double x = 17.0, y = 5.0;
    printf("%.2f\n", x / y);   // 3.40

    // 自增自减
    int i = 5;
    printf("%d\n", i++);   // 5(先用再加)
    printf("%d\n", i);     // 6
    printf("%d\n", ++i);   // 7(先加再用)

    // 注意:整数除法截断小数
    printf("%d\n", 1 / 2);   // 0,不是 0.5!
    return 0;
}

几个易错点:

二、关系运算符

关系运算符比较两个值,结果是 1(真)或 0(假)。C 没有真正的布尔类型(C99 才有 _Bool / bool),用整数 0/1 表示真假。

#include <stdio.h>
#include <stdbool.h>   // C99 的 bool 类型

int main(void) {
    int a = 10, b = 20;

    // 关系运算结果:1(真)或 0(假)
    printf("%d\n", a > b);     // 0(假)
    printf("%d\n", a < b);     // 1(真)
    printf("%d\n", a >= 10);   // 1
    printf("%d\n", a <= 10);   // 1
    printf("%d\n", a == b);    // 0(注意:== 不是 =)
    printf("%d\n", a != b);    // 1

    // C89 没有 bool,用 int 0/1
    // C99 引入 bool(来自 stdbool.h)
    bool is_bigger = a > b;
    printf("is_bigger = %d\n", is_bigger);   // 0

    // 经典坑:把 == 写成 =(赋值)
    if (a = 5) {        // 这是赋值!a 变成 5,非0,恒真
        printf("总会执行\n");
    }
    return 0;
}

新手最大的坑:把相等比较 == 写成赋值 =if (a = 5) 是合法的(把 5 赋给 a,然后判断 a 非0,恒真),但几乎肯定是 bug。养成习惯:比较常量写左边 if (5 == a),这样写错成 = 编译器会报错。

三、逻辑运算符

逻辑运算符组合多个条件:

#include <stdio.h>
#include <stdbool.h>

int main(void) {
    int age = 25;
    bool is_student = true;

    // 逻辑运算:&& 与、|| 或、! 非
    // 结果同样:1(真)或 0(假)

    // && (与):两边都真才真
    printf("%d\n", (age >= 18) && (age <= 60));   // 1

    // || (或):一边真就真
    printf("%d\n", (age < 18) || (age > 60));     // 0

    // ! (非):取反
    printf("%d\n", !is_student);                  // 0

    // 短路求值(重要!)
    // && 如果左边为假,右边不计算
    // || 如果左边为真,右边不计算
    int x = 0;
    if (x != 0 && 10/x > 1) {   // x==0 时不会算 10/x,避免除0
        printf("不会执行\n");
    }

    // C 把 0 当假,任何非 0 都当真(包括负数)
    if (-1) printf("-1 也算真\n");   // 会打印
    if (0)  printf("0 才是假\n");    // 不打印
    return 0;
}

短路求值是逻辑运算的关键特性:

这个特性常用来避免空指针、除零等错误:if (p != NULL && p->value > 0)。如果 p 是 NULL,后面的访问就不会执行,避免了崩溃。

四、位运算符(C 的特色)

位运算直接对整数的三进制位操作,这是 C 区别于 Java/Python(虽然它们也有位运算,但用得少)的地方。底层编程、协议解析、权限控制都离不开它:

#include <stdio.h>

int main(void) {
    unsigned char a = 0b11001010;  // 202(二进制字面量 C14 起支持)
    unsigned char b = 0b10110101;  // 181
    // 旧写法:a = 0xCA; b = 0xB5;(十六进制)

    printf("a & b = %d\n", a & b);    // 按位与:168  (10001000)
    printf("a | b = %d\n", a | b);    // 按位或:215  (11010111)
    printf("a ^ b = %d\n", a ^ b);    // 按位异或:47 (00101111)
    printf("~a    = %d\n", (unsigned char)~a);  // 取反:53
    printf("a << 2 = %d\n", a << 2);  // 左移2位:808 (相当于 *4)
    printf("a >> 2 = %d\n", a >> 2);  // 右移2位:50  (相当于 /4)

    // 经典技巧:位运算做权限标志
    unsigned int perm = 0;
    perm |= (1 << 0);    // 加读权限
    perm |= (1 << 1);    // 加写权限
    printf("有读权限? %d\n", (perm & (1 << 0)) != 0);  // 1
    printf("有执行权限? %d\n", (perm & (1 << 2)) != 0); // 0

    // XOR 加密/解密(对称)
    char c = 'A';
    char key = 7;
    char encrypted = c ^ key;    // 加密
    char decrypted = encrypted ^ key;  // 解密回 'A'
    return 0;
}

6 个位运算符:

常见用途:(1) 权限标志位(一个 int 存多个开关)、(2) XOR 加密(对称,加密解密用同一操作)、(3) 位掩码(取某几位)、(4) 高性能乘除(左移代替乘 2)。

五、其他运算符

#include <stdio.h>

int main(void) {
    int a = 10, b = 20;

    // 1. 三目条件运算符 ?:
    int max = (a > b) ? a : b;   // 等价于 if-else 简写
    printf("max = %d\n", max);   // 20

    // 2. 复合赋值运算符
    int x = 5;
    x += 3;   // 等价 x = x + 3 = 8
    x -= 2;   // x = 6
    x *= 4;   // x = 24
    x /= 5;   // x = 4
    x %= 3;   // x = 1
    x <<= 2;  // x = 4
    x &= 0xFF;// 位运算也支持复合

    // 3. sizeof(也是运算符)
    printf("int 大小: %zu\n", sizeof(int));

    // 4. 逗号运算符(从左到右,结果是最后一个)
    int r = (1, 2, 3);
    printf("r = %d\n", r);   // 3
    // 主要用在 for 循环里写多个表达式

    // 5. 取地址 &、解引用 *(指针篇细讲)
    int n = 42;
    int *p = &n;
    printf("*p = %d\n", *p);   // 42

    // 6. 成员访问 . 和 -> (结构体篇细讲)
    return 0;
}

几个特殊的:

六、运算符优先级(简化版)

C 有 15+ 级优先级,死记很难,记住几个常用规则就够:

实际写代码时,拿不准就加括号——既不会出错,又能提高可读性。比如 a & b == c 实际是 a & (b == c)(== 优先级高于 &),如果想先做位与,必须写 (a & b) == c

小结

算术 + - * / %、关系 > < == !=、逻辑 && || !、位运算 & | ^ ~ << >> 是 C 运算符的核心。注意整数除法截断、== 别写成 =、逻辑短路求值。优先级拿不准就加括号。下一篇我们看 C 的控制流——让程序学会判断和循环。

← 上一篇 C 数据类型

下一篇 C 控制流

✈️💬