目录

  • 算术操作符
  • 移位操作符
    • 右移操作符
    • 左移操作符
  • 位操作符
    • & 按位与
    • | 按位或
    • ^ 按位异或
  • 赋值操作符
  • 单目操作符
    • !逻辑取反
    • + –
    • & *
  • sizeof
    • ~ 按位取反
    • ++ 和 – –
  • 关系操作符
  • 逻辑操作符
  • 条件操作符
  • 逗号表达式
  • 下标引用、函数调用和结构成员

算术操作符

 + - * / %

1.对于 / 操作符,如果两个操作数都是整数,执行整数除法;只要有一边是浮点数就是浮点数的除法
2.操作符 % 为取余,两边的数必须都是整数,不能为浮点数。剩下的几个操作符都可以作用于整数和浮点数。

移位操作符

<< 左移操作符>> 右移操作符

1.操作数只能是整数
2.移动的是二进制

计算机中都是由二进制表示信息的,整数二进制有三种表示形式:原码、反码、补码
1.正整数的原码、反码、补码都是相同的
2.负整数的原码、反码、补码需要计算

1.无论该整数是正的还是负的都可以写出原码:根据正负直接写出的二进制序列就是原码。
2.十进制到二进制的转化方法:除2取余,逆序排列。

假如我们这里给个 int a = 15,15的二进制是1111,一个整型占4个字节,也就是32位,所以前28位都是0。二进制第一位是符号位,0为正,1为负。

int a = 15;// 0000 0000 0000 0000 0000 0000 0000 1111 原码// 0000 0000 0000 0000 0000 0000 0000 1111 反码// 0000 0000 0000 0000 0000 0000 0000 1111 补码
int a = -15;// 1000 0000 0000 0000 0000 0000 0000 1111 原码// 1111 1111 1111 1111 1111 1111 1111 0000 反码(符号位不变,按位取反)// 1111 1111 1111 1111 1111 1111 1111 0001 补码(按位取反,末位加1(反码加1)/从右往左遇见的第一个1不变,前面按位取反)

整数在计算机内存中存储的是补码,计算的时候使用补码计算。
所以移位移动的是二进制序列的补码

#includeint main(){int a = 15;int b = a >> 1; //右移printf("%d\n", b);return 0;}

右移操作符

右移运算分为两种:逻辑右移(右边丢弃,左边补0);算术右移(右边丢弃,左边补符号位)

左移操作符

左边丢弃,右边补0

不要移动负数位,标准未定义

位操作符

与移位操作符一样都是操作二进制
位操作符的操作数必须是整数

& 按位与

对应二进制位有0则0,全1为1

#includeint main(){int a = 3;// 0000 0000 0000 0000 0000 0000 0000 0011原码// 0000 0000 0000 0000 0000 0000 0000 0011补码int b = -5;// 1000 0000 0000 0000 0000 0000 0000 0101原码// 1111 1111 1111 1111 1111 1111 1111 1011补码printf("%d\n", a & b); // 有0则0,全1为1// 0000 0000 0000 0000 0000 0000 0000 0011// 1111 1111 1111 1111 1111 1111 1111 1011// 0000 0000 0000 0000 0000 0000 0000 0011 结果 3return 0;}

| 按位或

对应二进制位有1则1,全0为0

#includeint main(){int a = 3;// 0000 0000 0000 0000 0000 0000 0000 0011原码// 0000 0000 0000 0000 0000 0000 0000 0011补码int b = -5;// 1000 0000 0000 0000 0000 0000 0000 0101原码// 1111 1111 1111 1111 1111 1111 1111 1011补码printf("%d\n", a | b); // 有1则1,全0为0// 0000 0000 0000 0000 0000 0000 0000 0011 // 1111 1111 1111 1111 1111 1111 1111 1011 // 1111 1111 1111 1111 1111 1111 1111 1011 补码// 1000 0000 0000 0000 0000 0000 0000 0101 -5return 0;}

^ 按位异或

对应的二进制位不同为1,相同为0

#includeint main(){int a = 3;// 0000 0000 0000 0000 0000 0000 0000 0011原码// 0000 0000 0000 0000 0000 0000 0000 0011补码int b = -5;// 1000 0000 0000 0000 0000 0000 0000 0101原码// 1111 1111 1111 1111 1111 1111 1111 1011补码printf("%d\n", a ^ b); //不同为1,相同为0// 0000 0000 0000 0000 0000 0000 0000 0011 // 1111 1111 1111 1111 1111 1111 1111 1011 // 1111 1111 1111 1111 1111 1111 1111 1000 补码// 1000 0000 0000 0000 0000 0000 0000 1000 -8return 0;}

不使用中间变量,实现两个数的交换(按位异或)

#include int main(){int a = 3;int b = 5;/*常规做法int tmp = a;a = b; b = tmp;*///不允许使用中间变量/*a = a + b; //把和放到a中b = a - b; //b为和减去ba = a - b; //a为和减去b缺陷:a和b很大,二者的和会超过int的范围*/a = a ^ b;b = a ^ b;a = a ^ b;// a^a0// a^0a// a = 3;// b = 5;// a^b^a ?// a 0011// b 0101// a^b 0110// a^b^a 0110 0011—— 0101—— b// a^a^b a^a=0 0^b=b// a^b^a = a^a^b ,交换律printf("%d %d\n", a, b);return 0;}

赋值操作符

赋值操作符中除了**=**外,还有很多个复合赋值操作符, +=,-=,*=,/=,%=,>>=,<<=,&=,|=,^=

单目操作符

单目操作符的操作数只有一个

!逻辑取反

可以理解为把真的变成假的,把假的变成真的

#includeint main(){int x = 0;if (x == 0)printf("hello\n");if (!x)printf("world\n");if (x)printf("!\n");return 0;}

在上述代码中,有三个条件语句,第一个当x0,输出hello;第二个0为假,非0为真,所以 !x为真,输出world;第三个0为假,非0为真,所以x为假,不输出 !

+ –

这里的 +,是正值和负值的意思,并不是加和减的意思,-1的负号就是单目操作符,它的操作数只有一个;2-1的减号是双目操作符,它的操作数有两个,分别是21

& *

& 为取地址, * 不是乘的意思,它是间接访问操作符,也称作解引用操作符,两者通常应用于指针。

#includeint main() {int a = 1;int* pa = &a; //&a将a的地址取出来,放到pa变量中,类型是int **pa = 2; //间接访问操作符,通过pa中存放的地址找到指向的内容或者空间int b = *pa;return 0;}

sizeof

sizeof是操作符,不是函数。它可以求变量或者类型所占空间的大小,单位是字节。

#includeint main(){int a = 1;printf("%d\n", sizeof(int));printf("%d\n", sizeof(a));printf("%d\n", sizeof a);//printf("%d\n", sizeof int);错误写法return 0;}

除此之外,sizeof还可以计算数组的大小,单位同样是字节。

#includeint main(){int arr[10] = {0};printf("%d\n", sizeof(arr));printf("%d\n", sizeof(int [10])); //[]中的数字不能去掉//printf("%d\n", sizeof(int [])); 错误写法return 0;}

~ 按位取反

按位取反是对二进制进行取反。

#includeint main(){int a = 0;printf("%d\n", ~a);//0的补码是 0000 0000 0000 0000 0000 0000 0000 0000//对0的补码取反为1111 1111 1111 1111 1111 1111 1111 1111//取反后的原码为 1000 0000 0000 0000 0000 0000 0000 0001//所以结果是-1return 0;}

下面这段代码,问题分析都在注释中写出来了

#includeint main(){int a = 13;//方便起见,只写八位//13是 0000 1101//要得到 0001 1101真值为29//按位或是有1则1//可以将13与 0001 0000按位或//0001 0000是0000 0001左移4位得到,也就是将1左移4位,将a按位或0001 0000即可a |= (1 << 4);printf("%d\n", a);//通过0001 1101真值为29 //得到0000 1101真值为13//按位与是全1才1//将0001 1101 按位与 1110 1111,即对0001 0000按位取反,也就是将1左移4位,取反。按位与。a &= (~(1 << 4)); //不知道优先级的话可以都带上括号printf("%d\n", a);return 0;}

感兴趣可以琢磨琢磨下面的代码

#includeint main(){int a = 0;//第一种写法//while (scanf("%d", &a) == 1)//{//printf("%d\n", a);//}//第二种写法//while (scanf("%d", &a) != EOF)//{//printf("%d\n", a);//}//第三种写法while (~scanf("%d", &a)){printf("%d\n", a);}return 0;}

++ 和 – –

++– – 分别都有前置和后置两种,前置为先运算后使用,后置为先使用后运算

关系操作符

> >= < <= != ==
注意:===的区别

逻辑操作符

&& 逻辑与(并且)|| 逻辑或(或者)

条件操作符

语句1 " />2 : 语句3类似于if (语句1)语句2;else 语句3;

C语言中唯一的三目操作符

逗号表达式

语句1,语句2,语句3,语句n从左向右计算,整个表达式的结果是最后一个表达式的值

下标引用、函数调用和结构成员

1.下标引用操作符 []操作数:数组名 + 索引值2.函数调用操作符 ()第一个操作数是函数名,剩余操作数是传递给函数的参数。最少有一个操作数3.访问结构成员 .结构体.成员名-> 结构体指针->成员名
#include struct Stu{char name[10];int age;char sex[5];double score;};void set_age1(struct Stu stu){stu.age = 18;};void set_age2(struct Stu* pStu){pStu->age = 18;//结构成员访问}int main(){struct Stu stu;struct Stu* pStu = &stu;//结构成员访问stu.age = 20;//结构成员访问set_age1(stu);pStu->age = 20;//结构成员访问set_age2(pStu);return 0;}