运算符的种类以及基本用法
一、算术运算符(最基础)
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
+ | 加法 | 3+5=8 | 正数 / 加法运算 |
- | 减法 / 负号 | 5-3=2 | 减法或表示负数(如-5) |
* | 乘法 | 3*5=15 | 注意:不是×,是* |
/ | 除法 | 5/2=2 | 整数除法舍去小数,5.0/2=2.5 |
% | 取模(取余) | 5%2=1 | 仅适用于整数,除数不能为 0 |
算数运算符是字符型吗?
这是一个非常容易混淆的概念,我们需要区分“运算符本身”和“运算符在代码中的写法”。
1. 核心结论
- 算术运算符(如
+,-,*,/):它们是语法符号,代表一种操作动作。它们不是字符型数据(char),也不能像字符一样被存储、打印或参与数学计算。 - 字符型数据(
char):是用来存储单个字符(如'A','1','+')的数据类型。
2. 详细对比分析
为了让你彻底明白,我们来看一个具体的例子:
❌ 错误理解:把运算符当字符
如果你写:
char op = +; // ❌ 报错!编译器会懵:你想让 op 等于什么?这是错误的,因为+在这里被编译器理解为“加法动作”,而不是一个字符。
✅ 正确理解:字符型的'+'
如果你想把加号作为一个字符存起来(比如为了打印出来显示),你必须加上单引号:
char op = '+'; // ✅ 正确!这里 '+' 是一个字符数据,它的 ASCII 码是 43 printf("%c", op); // 输出:+3. 三种情况的对比表
| 写法 | 含义 | 数据类型 | 能否参与数学运算? | 例子 |
|---|---|---|---|---|
+ | 加法运算符 | 无类型 (语法符号) | 能(作为动作) | int c = a + b;(执行加法) |
'+' | 加号字符 | char(整型) | 能(作为数字 43) | int c = 'a' + '+';(97 + 43) |
"+" | 加号字符串 | char*(指针) | 不能 | printf("%s", "+"); |
4. 常见误区演示
误区一:我想动态选择运算符
很多初学者想这样写:
char op = '+'; int result = 10 op 5; // ❌ 严重错误!解释:C 语言不支持把字符变量'+'直接当成运算符用。编译器在编译时就必须知道你要做什么运算,它不会在运行时去读变量op里的字符然后执行加法。
- 解决方法:必须用
if或switch判断字符,然后手动执行对应的运算。if (op == '+') { result = 10 + 5; } else if (op == '-') { result = 10 - 5; }
误区二:运算符是字符串吗?
printf("%s", +); // ❌ 错误解释:+不是字符串,不能用%s打印。如果你想打印加号这个符号,要么直接写在格式串里printf("+"),要么用字符%c打印'+'。
5. 总结
- 算术运算符(
+,-,*,/,%) 是命令,告诉编译器“做加法”、“做减法”。它们不是数据。 - 字符型(
char) 是数据,用来存储信息。 - 如果你想存储或传递一个运算符号(比如用户输入了
+号),你需要用char op = '+';(注意单引号)。 - 如果你想执行运算,你必须直接在代码里写
a + b,或者通过if/switch根据字符变量来调用对应的运算符。
一句话口诀:
没引号是动作(运算符),单引号是数据(字符),双引号是文本(字符串)。
二、赋值运算符(赋值 / 更新变量)
| 运算符 | 名称 | 示例 | 等价写法 |
|---|---|---|---|
= | 基础赋值 | a=5 | — |
+= | 加后赋值 | a+=3 | a=a+3 |
-= | 减后赋值 | a-=3 | a=a-3 |
*= | 乘后赋值 | a*=3 | a=a*3 |
/= | 除后赋值 | a/=3 | a=a/3 |
%= | 取模后赋值 | a%=3 | a=a%3 |
<<= | 左移后赋值 | a<<=3 | a=a<<3 |
&= | 按位与赋值 | a&=3 | a=a&3 |
三、位运算符(操作二进制位)
| 运算符 | 名称 | 规则 | 示例(8 位二进制) |
|---|---|---|---|
& | 按位与 | 对应位都为 1 则为 1,否则为 0 | 00001111 & 00001000 = 00001000 |
| | | 按位或 | 对应位有一个 1 则为 1,否则为 0 | 00000111 | 00001000 = 00001111 |
^ | 按位异或 | 对应位不同则为 1,相同则为 0 | 00001111 ^ 00001000 = 00000111 |
~ | 按位取反 | 0 变 1,1 变 0(补码运算) | ~00000001 = 11111110(对应 - 2) |
<< | 左移 | 所有位左移 n 位,右侧补 0(等价 ×2ⁿ) | 1<<3 = 8(00000001→00001000) |
>> | 右移 | 所有位右移 n 位,正数左侧补 0,负数补 1 | 8>>3 = 1(00001000→00000001) |
在 C 语言中,按位取反运算有一个通用公式:
∼n=−(n+1) 例:~5=-(5+1)
核心用法:
| 置 1:num | (1<<n) → 把第 n 位设为 1;
& 清零:num & ~(1<<n) → 把第 n 位设为 0;
^ 取反:num ^ (1<<n) → 把第 n 位翻转
| 功能 | 表达式 | 原理简述 | 示例效果 |
|---|---|---|---|
| 设置为1 | `n | = (1 << k)` | 或运算:有1则1 |
| 清除为0 | n &= ~(1 << k) | 与+取反:构造“除k位外全1”的掩码 | 0111 → 0101 |
| 检查是否为1 | if (n & (1 << k)) | 与运算:结果为0则否,非0则是 | 0101 & 0100 ≠0 |
四、比较运算符(判断条件)
用于比较两个值的大小 / 相等关系,返回 1(真)或 0(假):
| 运算符 | 名称 | 示例 | 结果(真 = 1,假 = 0) |
|---|---|---|---|
> | 大于 | 5>3 | 1 |
< | 小于 | 5<3 | 0 |
>= | 大于等于 | 5>=5 | 1 |
<= | 小于等于 | 5<=3 | 0 |
== | 等于 | 5==3 | 0 |
!= | 不等于 | 5!=3 | 1 |
五、逻辑运算符(组合条件)
| 运算符 | 名称 | 规则 | 示例 |
|---|---|---|---|
&& | 逻辑与 | 两边都为真才为真,否则为假(短路运算) | (5>3)&&(2>1)=1 |
| || | 逻辑或 | 有一边为真就为真(短路运算) | (5>3)||(2>1)=1 |
! | 逻辑非 | 真变假,假变真 | !(5>3)=0 |
六、其他常用运算符
| 运算符 | 名称 | 示例 | 说明 |
|---|---|---|---|
++ | 自增 | a++/++a | 后置:先使用后 + 1;前置:先 + 1 后使用 |
-- | 自减 | a--/--a | 同上 |
() | 括号 | (a+b)*3 | 提升运算优先级 |
, | 逗号 | a=3,b=5 | 从左到右执行,返回最后一个值 |
七、运算符优先级表
| 优先级 | 类别 | 运算符 | 结合性 (方向) | 说明 |
|---|---|---|---|---|
| 1 | 括号/访问 | ()[]->. | 左 → 右 | 函数调用、数组下标、成员访问 |
| 2 | 单目运算符 | ++--+-!~*(解引用)&(取地址)sizeof(type)(强制转换) | 右 ← 左 | 自增自减、正负号、逻辑非、按位取反、指针操作 |
| 3 | 算术运算 | */% | 左 → 右 | 乘、除、取余 |
| 4 | 算术运算 | +- | 左 → 右 | 加、减 |
| 5 | 移位运算 | <<>> | 左 → 右 | 左移、右移 (你刚才问的在这里!) |
| 6 | 关系运算 | <<=>>= | 左 → 右 | 小于、大于等 |
| 7 | 相等运算 | ==!= | 左 → 右 | 等于、不等于 |
| 8 | 位与 | & | 左 → 右 | 按位与 (注意:优先级高于^和 ` |
| 9 | 位异或 | ^ | 左 → 右 | 按位异或 |
| 10 | 位或 | | | 左 → 右 | 按位或 (注意:优先级高于&&) |
| 11 | 逻辑与 | && | 左 → 右 | 逻辑与 (短路) |
| 12 | 逻辑或 | || | 左 → 右 | 逻辑或 (短路) |
| 13 | 条件运算 | ?: | 右 ← 左 | 三元运算符 (a ? b : c) |
| 14 | 赋值运算 | =+=-=*=/=%=<<=>>=&=^=|= | 右 ← 左 | 各种赋值 (优先级非常低!) |
| 15 | 逗号 | , | 左 → 右 | 逗号表达式 (优先级最低) |
