
• 算术操作符: + 、- 、* 、/ 、%
• 移位操作符: << 、 >>
• 位操作符: &、 | 、 ^ 、~
• 赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^=
• 单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型)
• 关系操作符: > 、>= 、< 、<= 、 == 、 !=
• 逻辑操作符: && 、||
• 条件操作符: ?、 :
• 逗号表达式: ,
• 下标引⽤: [ ]
• 函数调⽤: ()
• 结构成员访问: . 、->
+ 和 - 用来完成加法和减法
+ 和 - 都是有2个操作数的,位于操作符两端的就是它们的操作数,这种操作符也叫双⽬操作符。
#include <stdio.h>
int main()
{
int x = 2 + 3;
int y = 8 - 6;
printf("%d\n", x);
printf("%d\n", y);
return 0;
}运算符 * 用来完成乘法。
#include<stdio.h>
int main()
{
int a=5;
int b=6;
int c=a*b;
printf("%d\n",c);
return 0;
}运算符 / 用来完成除法
除号的两端如果是整数,执⾏的是整数除法,得到的结果也是整数。
#include<stdio.h>
int main()
{
int x=6/3;
float y=9/5;
printf("%d\n",x);
printf("%f\n",y);
return 0;
}上⾯⽰例中,尽管变量 y 的类型是 float (浮点数),但是 9 / 5 得到的结果是 1.0 ,⽽不是 1.8 。原因就在于C语⾔⾥⾯的整数除法是整除,只会返回整数部分,丢弃⼩数部分
如果希望得到浮点数的结果,两个运算数必须⾄少有⼀个浮点数,这时C语⾔就会进⾏浮点数除法
#include <stdio.h>
int main()
{
float x = 6.0 / 4; // 或者写成 6 / 4.0
printf("%f\n", x); // 输出 1.500000
return 0;
}运算符 % 表⽰求模(余)运算,即返回两个整数相除的余值。这个运算符只能⽤于整数,不能⽤于浮点数。
负数求模的规则是,结果的正负号由第⼀个运算数的正负号决定
#include <stdio.h>
int main()
{
printf("%d\n", 11 % -5); // 1
printf("%d\n",-11 % -5); // -1
printf("%d\n",-11 % 5); // -1
return 0;
}<<左移操作符
>>右移操作符
注:移位操作符的操作数只能是整数
移位规则:左边抛弃,右边补0
#include <stdio.h>
int main()
{
int num = 10;
int n = num<<1;
printf("n= %d\n", n);
printf("num= %d\n", num);
return 0;
}左移操作符演示:

移位规则:⾸先右移运算分两种:
1.逻辑右移:左边⽤0填充,右边丢弃
2.算术右移:左边⽤原该值的符号位填充,右边丢弃
#include <stdio.h>
int main()
{
int num = 10;
int n = num>>1;
printf("n= %d\n", n);
printf("num= %d\n", num);
return 0;
}逻辑右移一位演示:

算数右移一位演示:

(注意⚠:对于移位运算符,不要移动负数,这个是标准未定义的)
操作符 | 名称 | 功能 |
|---|---|---|
& | 按位与 | 两数补码按位相比,有0为0,同1为1 |
| | 按位或 | 两数补码按位相比,有1为1,同0为0 |
^ | 按位异或 | 两数补码按位相比,相同为0,相异为1 |
~ | 按位取反 | 对一个补码,把0变1,把1变0 |
(注:它们的操作数必须是整数)
int a = 3;
//a的原码:00000000000000000000000000000011
//a的反码:00000000000000000000000000000011
//a的补码:00000000000000000000000000000011
int b = -6;
//b的原码:10000000000000000000000000000110
//b的反码: 11111111111111111111111111111001
//b的补码:11111111111111111111111111111010
int c = a & b; //按位与,有0则为0,同1才为1
//a的补码:00000000000000000000000000000011
//b的补码:11111111111111111111111111111010
//c的补码:00000000000000000000000000000010
int d = a | b; //按位或,有1则为1,同0才为0
//a的补码:00000000000000000000000000000011
//b的补码:11111111111111111111111111111010
//d的补码:11111111111111111111111111111011
int e = a ^ b; //按位异或,相同为0,相异为1
//a的补码:00000000000000000000000000000011
//b的补码:11111111111111111111111111111010
//e的补码:11111111111111111111111111111001
int f = ~a;
//a的补码:00000000000000000000000000000011
//f的补码:11111111111111111111111111111100操作符只有⼀个操作数,被称为单⽬操作符。!、 ++、--、+(正)、-(负)、~ 、&、* 就是单⽬操作符,~ 前面已经介绍过了,& 和 *,在之后的指针章节中会讲解。
++是⼀种⾃增的操作符,⼜分为前置++和后置++,--是⼀种⾃减的操作符,也分为前置--和后置--
int a = 10;
int b = ++a;//++的操作数是a,是放在a的前⾯的,就是前置++
printf("a=%d b=%d\n",a , b);计算⼝诀:先+1,后使⽤
a原来是10,先+1,后a变成了11,再使⽤就是赋值给b,b得到的也是11,所以计算技术后,a和b都 是11,相当于这样的代码:
int a = 10;
a = a+1;
b = a;
printf("a=%d b=%d\n",a , b);int a = 10;
int b = a++;//++的操作数是a,是放在a的后⾯的,就是后置++
printf("a=%d b=%d\n",a , b);计算⼝诀:先使⽤,后+1
a原来是10,先使⽤,就是先赋值给b,b得到了10,然后再+1,然后a变成了11,所以直接结束后a是 11,b是10,相当于这样的代码:
int a = 10;
int b = a;
a = a+1;
printf("a=%d b=%d\n",a , b);与前置++是一个道理,只是把+1换成了-1
计算⼝诀:先-1,后使⽤
int a = 10;
int b = --a;//--的操作数是a,是放在a的前⾯的,就是前置--
printf("a=%d b=%d\n",a , b);//输出的结果是:9 9 同理后置--类似于后置++,只是把加⼀换成了减⼀
计算⼝诀:先使⽤,后-1
int a = 10;
int b = a--;//--的操作数是a,是放在a的后⾯的,就是后置--
printf("a=%d b=%d\n",a , b);//输出的结果是:9 10 +是正号,-是负号,都是单⽬操作符。运算符 + 对正负值没有影响,是⼀个完全可以省略的运算符,但是写了也不会报错。
运算符 - ⽤来改变⼀个值的正负号,负数的前⾯加上 - 就会得到正数,正数的前⾯加上 - 会得到负 数。
sizeof 是⼀个关键字,也是操作符,专⻔是⽤来计算sizeof的操作符数的类型⻓度的,单位是字 节。 sizeof 操作符的操作数可以是类型,也可是变量或者表达式,用于获取一个数据类型或变量在内存中所占的字节数。sizeof 的计算结果是 size_t 类型的
语法形式:
sizeof( 类型 )
sizeof 表达式
#include <stdio.h>
int main()
{
int a = 10;
printf("%zd\n", sizeof(a));
printf("%zd\n", sizeof a);//a是变量的名字,可以省略掉sizeof后边的()
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof(3 + 3.5));
return 0;
}语法形式:
(类型)
int a = 3.14;
//a的是int类型, 3.14是double类型,两边的类型不⼀致,编译器会报警告 为了消除这个警告,我们可以使⽤强制类型转换:
int a = (int)3.14;
//意思是将3.14强制类型转换为int类型,这种强制类型转换只取整数部分 我们使⽤强制类型转换都是万不得已的时候使⽤,如果不需要强制类型转化就能实现代码,这样⾃然更好的。
逻辑操作符用于执行布尔逻辑运算,基于一个或多个布尔值(真或假)来产生结果。
逻辑符优先级:"!"(逻辑非)最高,然后是"&&"(逻辑与),最后是"||"(逻辑或)
当两个操作数都为真时,结果为真。 示例:if (a > 0 && b > 0)
当至少一个操作数为真时,结果为真。 示例:if (a > 0 || b > 0)
反转操作数的布尔值。如果操作数为真,则结果为假;如果操作数为假,则结果为真。 示例:if (!(a > 0))
条间操作符也叫三目操作符(条件操作符也是唯一的三目操作符),是一种在许多编程语言中广泛使用的运算符,它允许基于某个条件表达式的真值来选择两个表达式之一的值
语法形式:
expression1 ? expression2 : expression3;
expression1 是一个条件表达式,expression2 是当条件为真时要计算的表达式,而 expression3 是当条件为假时要计算的表达式。整个条件操作符的结果是 expression2 或 expression3 中的一个,具体取决于条件表达式的值。
下面写一个例子:
//计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值,打印出结果
#include <stdio.h>
int main()
{
double sum = 0.0;
int i;
int sigh;
for (i = 1; i <= 100; i++)
{
sigh = (i % 2 ? -1 : 1);
sum += (1.0 / i) * sigh;
}
printf("%lf", sum);
return 0;
}逗号表达式,就是⽤逗号隔开的多个表达式。 逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。可以用来优化代码
语法形式:
exp1, exp2, exp3, …expN
举例分析:
a = get_val();
count_val(a);
while (a > 0)
{
//业务处理
//...
a = get_val();
count_val(a);
}如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
//业务处理
}它的作用就是在数组中对数组元素下标进行引用,以此来访问数组元素。下标引用操作符也是一个双目操作符,它的操作数有两个——数组名和索引值;下面我们通过实例来说明它的两个操作数:
int arr[10] = { 0 };//定义数组
//int——数组元素类型;
// int [10]——数组类型;
//arr——数组名;
//10——数组大小;
arr[0] = 0;
//arr——数组名;
//0——索引值;在这个数组中,下标引用操作符的操作对象就是arr和0;在使用下标引用操作符时,有几点需要注意:
函数调用操作符从操作对象性质的角度来理解,我们也可以认为它是一个双目操作符。因为对于函数调用操作符的操作对象从性质上看是只有两个——函数名和参数;但是实际上操作对象并不止两个,如下所示:
int a = 0, b = 1, c = 2;
printf("%d,%d,%d\n", a, b, c);
//printf——函数名;
//"%d,%d,%d\n", a, b, c——参数;在这个例子中我们可以看到对于函数调用操作符来说,它此时的操作对象是printf这个函数名以及括号内的参数;但是我们可以看到函数的参数此时有"%d,%d,%d\n"、a 、b 、c 这四个参数;所以我们从操作对象的性质上来看,它也是属于双目操作符,但是我们要清楚它的参数并不是只能有一个参数,它可以没有参数也可以有一个参数或者多个参数。
函数调用操作符我们需要掌握的是只要是在操作符内部的内容都是属于函数的参数,以及函数调用操作符的参数可以有一个,也可以有多个。
结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数
语法形式:
结构体变量.成员名
举例分析:
#include <stdio.h>
struct Point
{
int x;
int y;
}p = {1,2};
int main()
{
printf("x: %d y: %d\n", p.x, p.y);
return 0;
}有时候我们得到的不是⼀个结构体变量,⽽是得到了⼀个指向结构体的指针
语法形式:
结构体指针->成员名
#include <stdio.h>
struct Point
{
int x;
int y;
};
int main()
{
struct Point p = {3, 4};
struct Point *ptr = &p;
ptr->x = 10;
ptr->y = 20;
printf("x = %d y = %d\n", ptr->x, ptr->y);
return 0;
}(关于结构体的更多知识会在后续章节中讲解)
C语言中的各种操作符的分类及用法基本已经介绍完了,这么多的操作符的优先级也各不相同,我会连同表达式在后续章节中讲解,希望这篇内容对大家理解操作符能有帮助。最后感谢各位的阅读,咱们下一篇再见!!!