操作符分类:
算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下标引用,函数调用和结构成员
算术操作符
int main()
{
float b = 3 / 2;
printf("%f\n", a);
int a = 9 % 2;
printf("%d\n", a);
return 0;
}
//例如加减乘除这些。
移位操作符
整数的二进制表示有三种形式,原码,反码,补码。
正整数的原反补是相同的,
负整数的原反补的要计算的。
整数在内存中储存的是补码的二进制。
int a = 5;
//a有32给比特位,a的二进制位为
//00000000000000000000000000000101 --原码
//最高位的0是符号位,0表示正数,1表示负数。
int a = -5;
//10000000000000000000000000000101 --原码
//11111111111111111111111111111010 --反码是原码符号位不变,其他位按位取反。
//11111111111111111111111111111011 --反码加一即是补码
int main()
{
int a = 5;
int b = a << 1;
//00000000000000000000000000000101
//最高位的0移出去,后面补0进来
//00000000000000000000000000001010
printf("%d\n", a);
printf("%d\n", b);
//但是打印出来的是原码。需要计算得到原码。
return 0;
}
int main()
{
int a = 5;
int b = a >> 1;
//00000000000000000000000000000101
printf("a=%d b=%d\n", a, b);
return 0;
}
//右移的情况下,有两种:
//一种是算数右移:右边丢弃,左边补原符号位。
//一种是逻辑右移:右边丢弃,左边补0。
//采用哪一种是取决于编译器的。
不能写移动的数位为负数。
位操作符
& 按位与 (只有两个数的二进制同时为1,结果才为1,否则为0)
| 按位或 (参加运算的两个数只要两个数中的一个为1,结果就为1)
^ 按位异或 (对应的二进制位,相同为0,相异为1)
int main()
{
int a = 3;
int b = -5;
//int c = a & b;
//00000000000000000000000000000011 3
//int c = a | b;
//11111111111111111111111111111011 -5
int c = a ^ b;//异或
//11111111111111111111111111111000
//11111111111111111111111111110111
//10000000000000000000000000001000 -8(原码)
//对应的二进制位:相同位0,相异为1
printf("%d\n", c);
//00000000000000000000000000000011 -> 3的补码
//11111111111111111111111111111011 -> -5的补码
return 0;
}
a^a=0;
0^a=a;
不能创建临时变量(第三个变量),实现两个数的交换。
int main()
{
int a = 3;
int b = 5;
printf("a=%d b=%d\n", a, b);
//int tmp = a;
//a = b;
//b = tmp;
//a = a + b;
//b = a - b;
//a = a - b;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a=%d b=%d\n", a, b);
return 0;
}
赋值操作符
int weight = 120;
weight= 80;
double salary = 10000.0;
salary = 200000.0;
赋值操作符还可以连续使用:
int a = 10;
int x = 0;
int y = 20;
a = x = y +1;//连续赋值。
//从右往左连等,y+1的值赋给x,x再赋给a。
但是连续赋值可读性较差。
复合赋值符
+=
-=
*=
/=
>>=
<<=
&=
|=
^=
布尔类型
用来表示真假的变量。
int main()
{
_Bool flag1 = false;
bool flag2 = true;
if (flag2)
{
printf("hehe\n");
}
//C语言中0表示假,非0表示真
//int num = 10;
//if (num)
//{
//}
//if (!num)//num为假,做事情
//{
//}
//
return 0;
}
单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置,后置--
++ 前置,后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
&和*
int main()
{
//& 取地址操作符
//* 解引用操作符(间接访问操作符)
int a = 10;
int* pa = &a;
*pa = 20;//* - 解引用操作符
//
//*&a ==> a;
//
int arr[10] = {0};
&arr;//取出数组的地址,数组的地址应该放到【数组指针】中去
struct S s = {0};
struct S* ps = &s;
return 0;
}
sizeof
内部的表达式不参与计算。
int main()
{
int a = 10;
short s = 0;
printf("%d\n", sizeof(s = a + 2));//
//sizeof()中的表达式不参与计算,在编译的时候就被处理掉了。
printf("%d\n", s);
return 0;
}
为什么while(~scanf("%d",&n))可以终止循环?
while(scanf("%d",&n)!=EOF)
{}
当scanf读取失败的时候,返回EOF,EOF本质是-1。
-1的二进制序列为:
11111111111111111111111111111111,
按位取反为000000000000000000000000000。
所以读取失败时,EOF被按位取反成0后跳出了循环。从而实现循环终止。
--与++
int main()
{
int a = 3;
//int b = ++a;//前置++,先++,后使用//a=a+1,b=a
//int b = a++;//后置++,先使用,后++。//b=a,a=a+1
//int b = --a;//前置--,先--,后使用 //a=a-1,b=a
//int b = a--;//后置--,先使用,再-- //b=a,a=a-1
//printf("%d\n", b);
//printf("%d\n", ++a);
return 0;
}
逻辑操作符
&&逻辑与
||逻辑或
1&2 -->1
1&0 -->0
1|2 -->1
1|0 -->1
0|0 -->0
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++;
i = a++ || ++b || d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
//对于这种并且操作符,左边为假右边的就不会再计算了。
条件操作符
exp1?exp2:exp3
比如a>5?3:-3 如果a>5,那么整个表达式结果为3,否则为-3。
逗号表达式
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
//a>b后不管他,如何a=12,b=13
printf("a=%d b=%d\n", a, b);
printf("%d\n", c);//13
return 0;
}
下标引用操作符,函数调用操作符和结构成员
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("%d\n", arr[4]);//arr[4]--> *(arr+4)
printf("%d\n", 4[arr]);
//arr
//arr[4] = 5;//[] 就是下标引用操作符
//arr 4
return 0;
}
int Add(int x, int y)
{
return x + y;
}
int main()
{
int ret = Add(2, 3);//()函数调用操作符,操作数就是:Add,2,3
printf("%d\n", ret);
return 0;
}
struct Point
{
int x;
int y;
};
隐式类型转换
C的整形算数预算总是以缺省整形类型的精度来进行的。
为了获取这个精度,表达式中的字符和短整型操作数在使用前被转换为普通整形,这种转换被称为整形提升。
整形提升
int main()
{
char c1 = 3;
//00000000000000000000000000000011
//00000011 - c1
char c2 = 127;
//00000000000000000000000001111111
//01111111 - c2
char c3 = c1 + c2;
//00000000000000000000000000000011
//00000000000000000000000001111111
//00000000000000000000000010000010
//10000010 - c3
//提升时高位全补1。
//11111111111111111111111110000010(补码)
//11111111111111111111111110000001
//10000000000000000000000001111110
//-126
printf("%d\n", c3);//
//
return 0;
}
int main()
{
char c = 1;
printf("%u\n", sizeof(c));//1
printf("%u\n", sizeof(+c));//4
printf("%u\n", sizeof(-c));//4
return 0;
//只要有char类型参与计算,就会发生整形提升。
}
算术转换
如果某个操作符操作数为不同类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作无法进行,所以就有了算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int
//向上转换,