C语言 08 运算符

基本运算符

基本运算符包含常用的一些操作,常用的有:

  • 加法运算符:+
  • 减法运算符:-
  • 乘法运算符:*
  • 除法运算符:/
  • 取模运算符:%
  • 赋值运算符:=

先来看加法运算,这个就和数学中的是一样的了:

#include <stdio.h>

int main() {
    int a = 10, b = 5;
    printf("%d", a + b);
}
15

当然也可以像数学中那样写在一个数或是变量的最前面,表示是正数:

int a = +10, b = +5;

不过默认情况下就是正数,所以没必要去写一个 + 号


减法运算符其实也是一样的:

#include <stdio.h>

int main() {
    int a = 10, b = 5;
    printf("%d", a - b);
}
5

接着我们来看看乘法和除法运算:

#include <stdio.h>

int main() {
    int a = 20, b = 10;
    printf("%d, %d", a * b, a / b);
}
200, 2

还有取模运算:

#include <stdio.h>

int main() {
    int a = 20, b = 8;
    printf("%d", a % b);
}
4

取模运算就是计算余数


不过很遗憾,在 C 中没有指数相关的运算符,一般通过循环来实现。

运算符优先级

和数学中一样,运算符是有优先级的:

#include <stdio.h>

int main() {
    int a = 20, b = 10;
    printf("%d", a + a * b);
}
220

如果没有优先级,那么结果应该是400,但结果为220,说明先进行了乘法运算,再进行了加法运算,存在运算符优先级


在数学中,如果需要优先计算加减法再计算乘除法,那么就需要使用括号来提升加减法的优先级,C 语言也可以:

#include <stdio.h>

int main() {
    int a = 20, b = 10;
    printf("%d", (a + a) * b);
}
400

优先计算 a + a 的结果,再乘以 b


总结一下,运算符优先级如下,从左往右依次递减:
() > + - (做正负表示) > * / % > + - (做加减运算) > =


根据上面的优先级,我们来看看下面 a 的结果是什么:

#include <stdio.h>

int main() {
    int c;
    int a = (3 + (c = 2)) * 6;
    printf("%d", a);
}
30
#include <stdio.h>

int main() {
    int b, c;
    int a = (b = 5, c = b + 8);
    printf("%d, %d, %d", a, b, c);
}
13, 5, 13

逗号运算符从前往后依次执行,赋值结果是最后边的结果

自增自减运算符

正常情况下想要让一个变量值自增需要:

int a = 10;
a = a + 1;

现在只需要替换为:

int a = 10;
// 使用自增运算符,效果等价于 a = a + 1
++a;

并且它也是有结果的,除了做自增运算之外,它的结果是自增之后的值:

#include <stdio.h>

int main() {
    int a = 10;
    // 等价于int b = a = a + 1;
    int b = ++a;
    printf("%d", b);
}
11

当然也可以将自增运算符写到后面,和写在前面的区别是,它是先返回当前变量的结果,再进行自增的,顺序是完全相反的:

#include <stdio.h>

int main() {
    int a = 10;
    int b = a++;
    printf("a = %d, b = %d", a, b);
}
a = 11, b = 10

自增运算符++在前,那么先自增再出结果;自增运算符++在后,那么先出结果再自增。


那要是不想自增 1 而是自增 2 或是其他的数字呢?可以使用复合赋值运算符:

int a = 10;
// 等价于a = a + 5;
a += 5;

复合赋值运算符不仅仅支持加法,还支持各种各样的运算:

#include <stdio.h>

int main() {
    int a = 10;
    // 可以复合各种运算
    a %= 3;
    printf("a = %d", a);
}
a = 1

自减运算与自增运算同理:

#include <stdio.h>

int main() {
    int a = 10;
    a--;
    printf("a = %d", a);
}
a = 9

自增自减运算符和 +、- 做符号是的优先级一样,仅次于 () 运算符,所以在编写时一定要注意:

#include <stdio.h>

int main() {
    int a = 10;
    int b = 5 * --a;
    printf("b = %d", b);
}
b = 45

位运算符

当想要让一个变量的值变成 2 倍,只需要做一次乘法运算即可:

int a = 10;
// 很明显算完之后a就是20了
a *= 2;

但是现在可以利用位运算来快速进行计算:

int a = 10;
a = a << 1;   //也可以写成复合形式 a <<= 1

这样运算之后得到的结果居然也是 20,这是咋算出来的呢?实际上 << 是让所有的 bit 位进行左移操作,上面就是左移 1 位:
10 = 0000 1010 现在所以 bit 位上的数据左移一位 0001 0100 = 20


当然能左移那肯定也可以右移:

#include <stdio.h>

int main() {
    int a = 6;
    // 右移其实就是除以2的操作
    a = a >> 1;
    printf("a = %d", a);
}

a = 3

除了移动操作之外,也可以进行按位比较操作,先来看看按位与操作:

#include <stdio.h>

int main() {
    int a = 6, b = 4;
    // 按位与操作
    int c = a & b;
    printf("c = %d", c);
}

按位与是根据每个 bit 位来进行计算的:
4 = 00000100
6 = 00000110
按位与实际上就是让两个数的每一位都进行比较,如果两个数对应的bit位都是 1,那么结果的对应 bit 位上就是 1,其他情况一律为 0
所以计算结果为:00000100 = 4


除了按位与之外,还有按位或运算:

#include <stdio.h>

int main() {
    int a = 6, b = 4;
    int c = a | b;
    printf("%d", c);
}
6

按位或也是根据每个 bit 位来进行计算的:
4 = 00000100
6 = 00000110
按位或实际上也是让两个数的每一位都进行比较,如果两个数对应 bit 位上其中一个是 1,那么结果的对应bit位上就是 1,其他情况为 0。
所以计算结果为:00000110 = 6


还有异或和按位非(按位否定):

#include <stdio.h>

int main() {
    int a = 6, b = 4;
    // 注意^不是指数运算,表示按位异或运算,让两个数的每一位都进行比较
    // 如果两个数对应 bit 位上不同时为 1 或是同时为 0,那么结果就是 1,否则结果就是 0,所以这里的结果就是 2
    int c = a ^ b;
    // 按位否定针对某个数进行操作,它会将这个数的每一个 bit 位都置反,0 变成 1,1 变成 0
    a = ~a;
    printf("%d, %d", c, a);
}
2, -7

按位运算都是操作数据底层的二进制位来进行的。

逻辑运算符

逻辑运算符用于计算真和假,比如今天要么下雨要么不下雨,现在想要在程序中判断一下是否下雨了,这时就需要用到逻辑运算符:

#include <stdio.h>

int main() {
    int a = 10;
    // 现在想要判断 a 的值是否小于 0,可以直接使用小于符号进行判断,最后得到的结果只能是 1 或 0
    _Bool c = a < 0;
  	// 虽然结果是一个整数,但是这里推荐使用 _Bool 类型进行接收,它只能表示 0 和 1(更加专业一些)
    printf("c = %d", c);  
}
c = 0

实际上在 C 语言中,0 一般都表示为假,而非 0 的所有值(包括正数和负数)都表示为真,上面得到 1 表示真,0 表示假。


除了小于符号可以判断大小之外,还有:<<=>=>
比如现在想要判断字符 C 是否为大写字母:

#include <stdio.h>

int main() {
    char c = 'D';
    // 由于底层存储的就是 ASCII 码,这里可以比较 ASCII 码,也可以写成字符的形式
    printf("c是否为大写字母:%d", c >= 'A');
}
c是否为大写字母:1

但是发现,现在判断只能判断一个条件,也就是说只能判断 c 是否是大于等于 A 的,但是不能同时判断 c 的值是否是小于等于 Z 的,所以这时,就需要利用逻辑与和逻辑或来连接两个条件了:

#include <stdio.h>

int main() {
    char c = 'D';
    // 使用 && 表示逻辑与,逻辑与要求两边都是真,结果才是真
    printf("c是否为大写字母:%d", c >= 'A' && c <= 'Z');
}
c是否为大写字母:1

又比如现在希望判断 c 是否不是大写字母:

#include <stdio.h>

int main() {
    char c = 'D';
    // 使用 || 表示逻辑或,只要两边其中一个为真或是都为真,结果就是真
    printf("c是否不为大写字母:%d", c < 'A' || c > 'Z');
}
c是否不为大写字母:0

当然也可以判断 c 是否为某个字母:

#include <stdio.h>

int main() {
    char c = 'D';
    // 注意判断相等时使用==双等号
    printf("c是否为字母A:%d", c == 'A');
}
c是否为字母A:0

判断不相等也可以使用:

printf("c是否不为字母A:%d", c != 'A');

也可以对某个结果取反:

#include <stdio.h>

int main() {
    int i = 20;
    // 使用!来对结果取反,注意!优先级很高,一定要括起来,不然会直接对i生效
    printf("i是否不小于20:%d", !(i < 20));
}
i是否不小于20:1

这里要注意一下!如果直接作用于某个变量或是常量,那么会直接按照上面的规则(0 表示假,非 0 表示真)非 0 一律转换为 0,0 一律转换为 1。


这里可以结合三目运算符来使用这些逻辑运算符:

#include <stdio.h>

int main() {
    int i = 0;
    // 三目运算符格式为:expression ? 值1 : 值2,返回的结果会根据前面判断的结果来的
    char c = i > 10 ? 'A' : 'B';
    // 这里是判断 i 是否大于 10,如果大于那么 c 的值就是 A,否则就是 B
  	printf("%d", c);
}
66

最后,总结一下前面认识的所有运算符的优先级,从上往下依次降低:

运算符 解释 结合方式
() 同数学中的括号,直接提升到最高优先级 由左向右
! ~ + + – + - 否定,按位否定,增量,减量,正负号 由右向左
* / % 乘,除,取模 由左向右
+ - 加,减 由左向右
<< >> 左移,右移 由左向右
< <= >= > 小于,小于等于,大于等于,大于 由左向右
== != 等于,不等于 由左向右
& 按位与 由左向右
^ 按位异或 由左向右
| 按位或 由左向右
&& 逻辑与 由左向右
|| 逻辑或 由左向右
? : 条件 由右向左
= += -= *= /= &= ^= |= <<= >>= 各种赋值 由右向左
, 逗号(顺序) 由左向右
posted @ 2024-08-13 09:43  天航星  阅读(7)  评论(0编辑  收藏  举报