C语言操作符
操作符分类:
- 算数操作符:+ 、- 、* 、/ 、%
- 移位操作符:<< 、>>
- 位操作符:| 、& 、^
- 赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^=
- 单⽬操作符: !、++、–、&、*、+、-、~ 、sizeof、(类型)
- 关系操作符: > 、>= 、< 、<= 、 == 、 !=
- 逻辑操作符: && 、||
- 条件操作符: ? :
- 逗号表达式: ,
- 函数调⽤: ()
- 下标引⽤: []
- 结构成员访问: . 、->
有一部分操作符与二进制有关系,关于进制转换讲解请点击查看文章
原码,反码,补码
整数的2进制表示方法有三种即原码,反码,补码。
有符号的整数的三种表示方法有符号位和数值位两部分,2进制序列中,最高位被当作符号位,剩余的都是数值位。
最高位符号位用“0”表示“正”,“1”表示“负”。
正数的原反补都相同,负整数的三种表示方法各不相同。
- 原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码;
- 反码:将原码的符号位不变,其他位依次按位取反就可以得到反码;
- 补码:反码+1即可;
补码得到原码也可以使用符号位不变其他位按位取反+1的操作
对于整型来说:数据存放在内存中其实存放的是补码:
在计算机系统中,数值一律用补码来表示和存储。原因是使用补码可以将符号位和数值域通一处理;同时加法和减法也可以同意处理(因为CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外电路。
移位操作符
-
<< 左移操作符 -
>> 右移操作符
左移操作符:左边抛弃,右边补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;
}

右移操作符
- 算术右移:左边用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;
}

!!!不可以移动负数位,移动负数位是标准未定义的!!!
错误演示
int num=10;
num>>-1//error
位操作符
- 按位与:&
- 按位或:|
- 按位异或:^
- 按位取反:~
以上四个操作符的操作数必须是整数!!! - &: 与,对应二进制位同为1,则结果对应二进制位为1 比如 1&1结果为 1
- |: 或,对应二进制位只要有一个为1,则结果对应二进制位为1 比如 1 | 1 结果为1 1 | 0 结果为1
- ^: 异或,对应二进制位不相同,则结果对应二进制位为1 比如 1 ^0 的结果为1
//代码一
#include <stdio.h>
int main()
{
int num1 = -3;
int num2 = 5;
printf("%d\n", num1 & num2);
printf("%d\n", num1 | num2);
printf("%d\n", num1 ^ num2);
printf("%d\n", ~0);
return 0;
}
拓展问题:不创建第三个变量或临时变量,实现两个整数的交换
直接上代码:
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;
a = a^b;
printf("a = %d b = %d\n", a, b);
return 0;
}

//代码二
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a+b;
b = a-b;
a = a-b;
printf("a = %d b = %d\n", a, b);
return 0;
}
逗号表达式
exp1, exp2, exp3, …expN//逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果
/代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?
//代码2
if (a =b + 1, c=a / 2, d > 0)
//代码3
a = get_val();
count_val(a);
while (a > 0)
{
//业务处理
//...
a = get_val();
count_val(a);
}
如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
//业务处理
}
结构成员访问操作符
结构体声明
struct tag
{
member-list;
}variable-list;
//描述一个学生
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号不能丢
结构体变量的定义和初始化
//代码1:变量的定义
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//代码2:初始化。
struct Point p3 = {10, 20};
struct Stu //类型声明
{
char name[15];//名字
int age; //年龄
};
struct Stu s1 = {"zhangsan", 20};//初始化
struct Stu s2 = {.age=20, .name="lisi"};//指定顺序初始化
//代码3
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
结构成员访问操作符
结构体成员的直接访问:结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数。
#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;
}
//结构体指针->成员名
如有问题可以评论区留言
1929





