C 运算符
算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 --- 假设变量 A 的值为 10,变量 B 的值为 20
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 杂项运算符
算术运算符
假设变量 A 的值为 10,变量 B 的值为 20
| 运算符 | 描述 | 实例 |
|---|---|---|
| + | 把两个操作数相加 | A + B 将得到 30 |
| - | 从第一个操作数中减去第二个操作数 | A - B 将得到 -10 |
| * | 把两个操作数相乘 | A * B 将得到 200 |
| / | 分子除以分母 | B / A 将得到 2 |
| % | 取模运算符,整除后的余数 | B % A 将得到 0 |
| ++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
| – | 自减运算符,整数值减少 1 | A– 将得到 9 |
ATTENTION: ++/–所处的位置对于数据的影响 a++先用后加,++a先加后用
EXAMPLE: 以下实例演示了 a++ 与 ++a 的区别:
#include <stdio.h> int main() { int c; int a = 10; c = a++; printf("先赋值后运算:\n"); printf("Line 1 - c 的值是 %d\n", c ); printf("Line 2 - a 的值是 %d\n", a ); a = 10; c = a--; printf("Line 3 - c 的值是 %d\n", c ); printf("Line 4 - a 的值是 %d\n", a ); printf("先运算后赋值:\n"); a = 10; c = ++a; printf("Line 5 - c 的值是 %d\n", c ); printf("Line 6 - a 的值是 %d\n", a ); a = 10; c = --a; printf("Line 7 - c 的值是 %d\n", c ); printf("Line 8 - a 的值是 %d\n", a ); }
先赋值后运算:
Line 1 - c 的值是 10
Line 2 - a 的值是 11
Line 3 - c 的值是 10
Line 4 - a 的值是 9
先运算后赋值:
Line 5 - c 的值是 11
Line 6 - a 的值是 11
Line 7 - c 的值是 9
Line 8 - a 的值是 9
关系运算符
变量A 的值为 10,变量 B 的值为 20
| 运算符 | 描述 | 实例 |
|---|---|---|
| 检查两个操作数的值是否相等,如果相等则条件为真。 | (A B) 为假。 | |
| != | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
| > | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 为假。 |
| < | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
| >= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 为假。 |
| <= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
逻辑运算符
假设变量 A 的值为 1,变量 B 的值为 0,则:
| 运算符 | 描述 | 实例 |
|---|---|---|
| && | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
| | | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 | (A | B) 为真。 |
| ! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 | !(A && B) 为真。 |
TIP: 与&&, 或 | ,非 ! 对于 &&,有零出零,全一出一 对于 | , 有一出一,全零出零
位运算符
位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
| p | q | p & q | p | q | p ^ q |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 |
EXAMPLE 假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:
A = 0011 1100 B = 0000 1101
A&B = 0000 1100 A|B = 0011 1101 A^B = 0011 0001 ~A = 1100 0011
假设变量 A 的值为 60,变量 B 的值为 13,则:
| 运算符 | 描述 | 实例 |
|---|---|---|
| & | 对两个操作数的每一位执行逻辑与操作,如果两个相应的位都为 1,则结果为 1,否则为 0。 按位与操作,按二进制位进行“与”运算。运算规则: 0&0=0; 0&1=0; 1&0=0; 1&1=1; |
(A & B) 将得到 12,即为 0000 1100 |
| | | 对两个操作数的每一位执行逻辑或操作,如果两个相应的位都为 0,则结果为 0,否则为 1。 按位或运算符,按二进制位进行“或”运算。运算规则: 0|0=0; 0|1=1; 1|0=1; 1|1=1; |
(A | B) 将得到 61,即为 0011 1101 |
| ^ | 对两个操作数的每一位执行逻辑异或操作,如果两个相应的位值相同,则结果为 0,否则为 1。 异或运算符,按二进制位进行“异或”运算。运算规则: 0^0=0; 0^1=1; 1^0=1; 1^1=0; |
(A ^ B) 将得到 49,即为 0011 0001 |
| ~ | 对操作数的每一位执行逻辑取反操作,即将每一位的 0 变为 1,1 变为 0。 取反运算符,按二进制位进行“取反”运算。运算规则: ~1=-2; ~0=-1; |
(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
| << | 将操作数的所有位向左移动指定的位数。左移 n 位相当于乘以 2 的 n 次方。 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 |
A << 2 将得到 240,即为 1111 0000 |
| >> | 将操作数的所有位向右移动指定的位数。右移n位相当于除以 2 的 n 次方。 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补 0,负数左补 1,右边丢弃。 |
A >> 2 将得到 15,即为 0000 1111 |
赋值运算符
| 运算符 | 描述 | 实例 |
|---|---|---|
| = | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
| += | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
| -= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= |
乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
| /= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
| %= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
| <<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
| >>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
| &= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
| ^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
| |= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
杂项运算符 ↦ sizeof & 三元
| 运算符 | 描述 | 实例 |
|---|---|---|
| sizeof() | 返回变量的大小。 | sizeof(a) 将返回 4,其中 a 是整数。 |
| & | 返回变量的地址。 | &a; 将给出变量的实际地址。 |
| * | 指向一个变量。 | *a; 将指向一个变量。 |
| ? : | 条件表达式 | 如果条件为真 ? 则值为 X : 否则值为 Y |
EXAMPLE
#include <stdio.h> int main() { int a = 4; short b; double c; int* ptr; /* sizeof 运算符实例 */ printf("Line 1 - 变量 a 的大小 = %lu\n", sizeof(a) ); printf("Line 2 - 变量 b 的大小 = %lu\n", sizeof(b) ); printf("Line 3 - 变量 c 的大小 = %lu\n", sizeof(c) ); /* & 和 * 运算符实例 */ ptr = &a; /* 'ptr' 现在包含 'a' 的地址 */ printf("a 的值是 %d\n", a); printf("*ptr 是 %d\n", *ptr); /* 三元运算符实例 */ a = 10; b = (a <mark> 1) ? 20: 30; printf( "b 的值是 %d\n", b ); b = (a </mark> 10) ? 20: 30; printf( "b 的值是 %d\n", b ); }
Line 1 - 变量 a 的大小 = 4
Line 2 - 变量 b 的大小 = 2
Line 3 - 变量 c 的大小 = 8
a 的值是 4
*ptr 是 4
b 的值是 30
b 的值是 20
C 中的运算符优先级
C/C++ 运算符优先级与结合性表
| 优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
|---|---|---|---|---|---|
| 1 | [] |
数组下标 | 数组名[常量表达式] | 左到右 | – |
| 1 | () |
圆括号 | (表达式)/函数名(形参表) | 左到右 | – |
| 1 | . |
成员选择(对象) | 对象.成员名 | 左到右 | – |
| 1 | -> |
成员选择(指针) | 对象指针->成员名 | 左到右 | – |
| 2 | - |
负号运算符 | -表达式 | 右到左 | 单目运算符 |
| 2 | ~ |
按位取反运算符 | ~表达式 | 右到左 | 单目运算符 |
| 2 | ++ |
自增运算符 | ++变量名/变量名++ | 右到左 | 单目运算符 |
| 2 | -- |
自减运算符 | –变量名/变量名– | 右到左 | 单目运算符 |
| 2 | * |
取值运算符 | *指针变量 | 右到左 | 单目运算符 |
| 2 | & |
取地址运算符 | &变量名 | 右到左 | 单目运算符 |
| 2 | ! |
逻辑非运算符 | !表达式 | 右到左 | 单目运算符 |
| 2 | (类型) |
强制类型转换 | (数据类型)表达式 | 右到左 | 单目运算符 |
| 2 | sizeof |
长度运算符 | sizeof(表达式) | 右到左 | 单目运算符 |
| 3 | / |
除 | 表达式/表达式 | 左到右 | 双目运算符 |
| 3 | * |
乘 | 表达式*表达式 | 左到右 | 双目运算符 |
| 3 | % |
余数(取模) | 整型表达式%整型表达式 | 左到右 | 双目运算符 |
| 4 | + |
加 | 表达式+表达式 | 左到右 | 双目运算符 |
| 4 | - |
减 | 表达式-表达式 | 左到右 | 双目运算符 |
| 5 | << |
左移 | 变量<<表达式 | 左到右 | 双目运算符 |
| 5 | >> |
右移 | 变量>>表达式 | 左到右 | 双目运算符 |
| 6 | > |
大于 | 表达式>表达式 | 左到右 | 双目运算符 |
| 6 | >= |
大于等于 | 表达式>=表达式 | 左到右 | 双目运算符 |
| 6 | < |
小于 | 表达式<表达式 | 左到右 | 双目运算符 |
| 6 | <= |
小于等于 | 表达式<=表达式 | 左到右 | 双目运算符 |
| 7 | <mark> |
等于 | 表达式表达式 | 左到右 | 双目运算符 |
| 7 | != |
不等于 | 表达式!=表达式 | 左到右 | 双目运算符 |
| 8 | & |
按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
| 9 | ^ |
按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
| 10 | | |
按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
| 11 | && |
逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
| 12 | || |
逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
| 13 | ?: |
条件运算符 | 表达式1?表达式2:表达式3 | 右到左 | 三目运算符 |
| 14 | = |
赋值运算符 | 变量=表达式 | 右到左 | – |
| 14 | /= |
除后赋值 | 变量/=表达式 | 右到左 | – |
| 14 | *= |
乘后赋值 | 变量*=表达式 | 右到左 | – |
| 14 | %= |
取模后赋值 | 变量%=表达式 | 右到左 | – |
| 14 | += |
加后赋值 | 变量+=表达式 | 右到左 | – |
| 14 | -= |
减后赋值 | 变量-=表达式 | 右到左 | – |
| 14 | <<= |
左移后赋值 | 变量<<=表达式 | 右到左 | – |
| 14 | >>= |
右移后赋值 | 变量>>=表达式 | 右到左 | – |
| 14 | &= |
按位与后赋值 | 变量&=表达式 | 右到左 | – |
| 14 | ^= |
按位异或后赋值 | 变量^=表达式 | 右到左 | – |
| 14 | |= |
按位或后赋值 | 变量|=表达式 | 右到左 | – |
| 15 | , |
逗号运算符 | 表达式,表达式,… | 左到右 | – |
NOTE 同一优先级的运算符,运算次序由结合方向所决定。
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
这里列出C语言的 15 级运算符优先级表。规律是:同一优先级的运算符,运算次序由“结合方向”决定。
| 优先级 | 运算符分类 | 符号 | 功能说明 | 结合方向 |
|---|---|---|---|---|
| 1 (最高) | 后缀运算符 | () [] -> . |
圆括号、数组下标、指向结构体成员、结构体成员 | 左到右 |
| 2 | 单目运算符 | ! ~ ++ -- + - * & sizeof (类型) |
逻辑非、按位取反、自增自减、正负号、指针解引用、取地址、求长度、强制类型转换 | 右到左 |
| 3 | 乘除运算符 | * / % |
乘法、除法、取余 | 左到右 |
| 4 | 加减运算符 | + - |
加法、减法 | 左到右 |
| 5 | 移位运算符 | << >> |
左移、右移 | 左到右 |
| 6 | 关系运算符 | < <= > >= |
小于、小于等于、大于、大于等于 | 左到右 |
| 7 | 相等运算符 | == != |
等于、不等于 | 左到右 |
| 8 | 按位与 | & |
按位与 | 左到右 |
| 9 | 按位异或 | ^ |
按位异或 | 左到右 |
| 10 | 按位或 | | |
按位或 | 左到右 |
| 11 | 逻辑与 | && |
逻辑与 (短路运算) | 左到右 |
| 12 | 逻辑或 | | |
逻辑或 (短路运算) | 左到右 |
| 13 | 条件运算符 | ?: |
三目运算符 (条件 ? 真 : 假) |
右到左 |
| 14 | 赋值运算符 | = += -= *= /= 等 |
赋值及复合赋值 | 右到左 |
| 15 (最低) | 逗号运算符 | , |
顺序求值 | 左到右 |
核心记忆口诀与避坑指南
如果觉得表格太长难以记住,可以记住这个经过提炼的优先级大类口诀:
TIPS 初等(括号/成员) > 单目 > 算术 > 关系(比较) > 逻辑 > 条件 > 赋值 > 逗号
补充说明
- C 和 C++ 采用”向零取整“的方法,与 Python 的”向下取整“(地板除法)区分
%运算符要求参加运算的运算对象(即操作数)为整数,结果也为整数。如8%3,结果为2