今天给大家分享C语言中操作符嘻嘻
操作符在平常编程中十分常见,也可以说经常用到。
C语言中操作符有: 算术操作符、 移位操作符、 赋值操作符、 单⽬操作符等多种操作符,让我们一起来详细了解吧。
目录
一、算术操作符
算术操作符: + 、- 、* 、/ 、%
+、-、*、/、这五个操作符大家都知道,那就给大家说说%操作符吧,%操作符是对一个数取模,也就是余数,一个数被另一个数除的余数,要注意的是%两边的操作数都要是整数。
二、位移操作符
左移操作符:<<
右移操作符:>>
注:移位操作符的操作数只能是整数。
1、左移操作符
移位规则:左边抛弃、右边补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;
}
2、右移操作符
移位规则:⾸先右移运算分两种:
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),两者结果不同:
-
逻辑右移:左侧补0,数值可能变为极大正数。
-
算术右移:左侧补1,保留负号(数值等价于除以2)。
-
警告⚠⚠:对于移位运算符,不要移动负数位,这个是标准未定义的。
三、位操作符:&、|、^、~
1、&(按位与):精准的“筛选器”
定义:对两个整数的二进制表示逐位进行比较,仅当两者对应位均为 1
时,结果位才为 1
,否则为 0。
示例:
#include <stdio.h>
int main() {
int num = 6; // 二进制:0110
if ((num & 1) == 0) {
printf("偶数\n"); // 输出:偶数
}
else
{
printf("奇数\n");
}
return 0;
}
可以用来判断奇偶数。
2、 |(按位或):高效的“组合器”
定义:对两个整数的二进制表示逐位进行比较,只要有一位是 1
,结果位即为 1,两位为0就为0。
它会对两个数的每一位进行或运算,只要有一位是1结果就是1。常见用途是组合多个标志位,比如在设置权限时,将多个权限合并。比如,一个文件可能有读、写、执行权限,用或运算来组合这些权限。例如,READ = 1, WRITE = 2, EXECUTE =4,组合READ和WRITE就是1 | 2 =3。需要说明这种用法的高效性,避免多次判断。
3、^(按位异或):聪明的“差异探测器”
定义:比较两个二进制数的每一位,若不同则为 1
,相同则为 0
。
它比较的是两个位不同则为1,相同则为0。异或有很多有趣的应用,比如交换两个变量的值而不需要临时变量,或者用于简单的加密,因为异或同一个数两次会恢复原值。另外,异或还可以用于找出数组中只出现一次的数字,比如在“只出现一次的数字”这个问题中,利用异或的交换律和结合律,将所有数字异或后剩下的就是那个唯一的数字。需要举例子说明,比如交换a和b的值,或者加密解密过程。
示例:不建立临时变量来给另两个整数交换值
int main()
{
int a = 10;
int b = 20;
printf("交换前:a=%d b=%d\n", a, b);;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
运行结果:
这里a^a等于多少呢?a^a是等0的那a按位与一个0会等于a,我们就可以根据这个特性来计算给两个整数来交换值。
4、 ~(按位非):翻转的“镜像大师”
定义:一元操作符,将二进制数的每一位取反(0
变 1
,1
变 0
)。
注意:在补码表示中,~x
等价于 -x-1
(如 ~5
结果为 -6
)。
它是一元操作符,对每一位取反。即0变1,1变0。需要注意的是在不同编程语言中,对负数的处理可能不同,尤其是补码表示的问题。应用场景可能包括掩码反转,或者配合其他位操作符使用。比如,要清除某个位,可以用& ~mask的方式。
四、单⽬操作符
单⽬操作符有这些:
!、++、--、&、*、+、-、~ 、sizeof、(类型)
单⽬操作符的特点是只有⼀个操作数,这里就不过多介绍了。(偷懒嘻嘻)
五、逗号表达式
逗号表达式,就是⽤逗号隔开的多个表达式。 逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。
示例:
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
printf("%d",c);
return 0;
}
六、下标访问[]、函数调⽤()
1、下标访问[ ]
操作数:⼀个数组名+⼀个索引值(下标)
2、 函数调⽤()
接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h>
void test1()
{
printf("hehe\n");
}
void test2(const char *str)
{
printf("%s\n", str);
}
int main()
{
test1(); //这⾥的()就是作为函数调⽤操作符。
test2("hello bit.");//这⾥的()就是函数调⽤操作符。
return 0;
}
七、结构成员访问操作符
C语⾔已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类 型还是不够的,假设我想描述学⽣,描述⼀本书,这时单⼀的内置类型是不⾏的。描述⼀个学⽣需要 名字、年龄、学号、⾝⾼、体重等;描述⼀本书需要作者、出版社、定价等。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;
}
运行结果:
使⽤⽅式:结构体指针->成员名