C语言操作符,包含算术操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符、逗号操作符以及下标引用操作符等。
1、算术操作符
算术操作符包含 + ,- ,*, / ,%。
①除了%操作符之外,其他的几个操作符可以作用于整数和浮点数。
②对于/操作符,如果两个操作数都为整数,执行整数除法,而只要有浮点数执行的就是浮点数除法。
③%操作符的两个操作数必修都为整数,返回的是整出之后的余数。
int main()
{
int ret = 9 / 2;//对于两边都是整数,执行整数除法。
printf("%d\n", ret); ret==4
double ret1 = 9.0 / 2; ret==4.500000
printf("%lf\n", ret1);//操作数中有浮点数,执行浮点数除法
int ret2 = 9 % 2;//取模操作符,整除之后看余数,对于取模操作符,两个操作数只能是整数,不能是浮点数,返回的是整除之后的余数。
printf("%d\n", ret2); ret==1
return 0;
}
2、移位操作符
<<左移操作符 >>右移操作符
移位操作符移动的是二进制位,对于整数的二进制位有三种形式,即原码 反码 补码 。对于正整数来说,原码 反码 补码都一样,对于负整数来说,原码 反码 补码需要计算:
原码是按照数字正负写出的32位二进制数,首先根据数的正负得到最高位的符号位,正整数为0,负整数为1
2:
00000000 00000000 00000000 00000010
-2:
10000000 00000000 00000000 00000010
①正整数原码 反码 补码的计算:(以1为例)
首先,正整数符号位为0
原码:00000000 00000000 00000000 00000001,由于正整数原码 反码 补码都一样,所以得到
反码:00000000 00000000 00000000 00000001
补码:00000000 00000000 00000000 00000001
②负整数原码 反码 补码的计算:(以-1为例)
首先,负整数符号位为1
原码:10000000 00000000 00000000 00000001,对于负整数原码 反码 补码需要计算
负整数的反码为原码符号位不变,其他位按位取反,即;
反码:111111111 11111111 11111111 11111110
负整数的补码为反码+1,即;
补码:111111111 11111111 11111111 11111111
回到上述移位操作符:
int main()
{
<<左移操作符
int a = 5;
int b = b << 1;
printf("%d\n", b);
对于正整数5;
原码:00000000 00000000 00000000 00000101
反码:00000000 00000000 00000000 00000101
补码:00000000 00000000 00000000 00000101
左移:00000000 00000000 00000000 00001010 左边丢弃,右边补0
int c = -1;
int d = c << 1;
printf("%d\n", d);//打印的是原码的值
对于负整数-1;
原码:10000000 00000000 00000000 00000001 开头的1是符号位,表示负数。
反码:11111111 11111111 11111111 11111110
补码:11111111 11111111 11111111 11111111
左移:11111111 11111111 11111111 11111110 这里得到的是左移后的补码,需要得到原码
新反码:11111111 11111111 11111111 11111101
新原码:10000000 00000000 00000000 00000010 得到-2
>>右移操作符
逻辑右移:右边丢弃,左边补0。
算数右移:右边丢弃,左边补充原符号位。
对于正整数,逻辑右移和算术右移的结果一样
对于负整数,当前编译器采用的是算术右移。
int c = -1;
int d = c >> 1;
printf("%d\n", d);
return 0;
}
对于移位操作符,不要移动负数位!!!! 例如:int a>>-1(不合法)
对于移位操作符,必须是两个操作位都是整型
3、位操作符
位操作符包含:按位与&、按位或|,按位异或^
int main()
{
int a = 3;
对于a,a是个正整数,原码 反码 补码都相同
原码:00000000 00000000 00000000 00000011
反码:00000000 00000000 00000000 00000011
补码:00000000 00000000 00000000 00000011
int b = -2;
对于b,b是个负整数,原码 反码 补码需要计算
原码:10000000 00000000 00000000 00000010 最高位的1为符号位,表示这个数是负整数。
反码:11111111 11111111 11111111 11111101
补码:11111111 11111111 11111111 11111110
按位与:
int c = a & b;// 二进制按位与的计算规则,只要有0结果就为0,同时为1则为1
a&b: 00000000 00000000 00000000 00000011 3的补码
11111111 11111111 11111111 11111110 -2的补码
00000000 00000000 00000000 00000010 3和-2按位与的结果,也为补码
a&b反码:00000000 00000000 00000000 00000010
a&b补码:00000000 00000000 00000000 00000010
printf("%d\n", c); %d,说明我们要打印C的值,以有符号的形式,得到-2。
按位或:
int d = a | b; //二进制按位或的计算规则,只要有1就为1
a|b: 00000000 00000000 00000000 00000011 3的补码
11111111 11111111 11111111 11111110 -2的补码
11111111 11111111 11111111 11111111 3和-2按位或的结果,也为补码
上述得到的补码计算出新的补码 反码
a|b补码:11111111 11111111 11111111 11111111
a|b反码:11111111 11111111 11111111 11111110
a|b原码:10000000 00000000 00000000 00000001
printf("%d\n", d); 得到结果为-1
按位异或:
int f = a ^ b;//二进制按位异或的计算规则为,相同为0,相异为1.
a^b: 00000000 00000000 00000000 00000011 3的补码
11111111 11111111 11111111 11111110 -2的补码
11111111 11111111 11111111 11111101 3和-2按位异或的结果,也为补码
上述得到的补码计算出新的补码 反码
a^b补码: 11111111 11111111 11111111 11111101
a^b反码: 11111111 11111111 11111111 11111100
a^b原码: 10000000 00000000 00000000 00000011
printf("%d\n", f);得到结果为-3
return 0;
}
4、赋值操作符
赋值操作符包含:=、+=、-=、/=、*=、>>=、<<=等
int main()
{
int weight = 120; 将120赋值给weight整型变量
weight = 89; 将89赋值给weight整型变量,相当于修改
double salary = 10000.0; 将10000.0赋值给salary浮点型变量
salary = 20000.0; 将20000.0赋值给salary浮点型变量,相当于修改
return 0;
}
复合赋值
int main()
{
int a=10;
a=a+10;
a+=10; a=a+10可写成a+=10
a=a-10;
a-=10; a=a-10可写成a-=10
a=a/10;
a/=10; a=a/10可写成a/=10
a=a*10;
a*=10; a=a*10可写成a*=10
a=a>>1;
a>>=1; a=a>>1可写成a>>=1
a=a<<1
a<<=1 a=a<<1可写成a<<=1
return 0
}
5、单目操作符
单目操作符包含:sizeof ++ -- ! & *
①sizeof操作符,不实函数,是计算变量或类型创建变量的内存大小,单位是字节,和内存中存放什么数据没有关系
int main()
{
char arr[10] = "abc";
printf("%d\n", sizeof(arr));//10个字节
printf("%d\n", strlen(arr));//字符串的长度,为3。关注的是内存中是否有\o,计算的是\0之前出现的字符个数。
int a = 10;
printf("%d\n", sizeof(a));//4
printf("%d\n", sizeof a);//4
printf("%d\n", sizeof(int));//4
//printf("%d\n", sizeof int);//这种写法是错误的
int b = 5;
short s = 10;
printf("%d\n", sizeof(s = b + 2));//发生截断,最后只能是short类型数据,大小为2字节
//sizeof内部的表达式是不参与运算的,也就是上述表达式2不会发生计算,直接判断s的数据类型大小。
printf("%d\n", s);
return 0;
}
②++ --操作符
int main()
{
int a = 10;
int b = a++;//后置++,先使用,再加加
int c = ++a;//前置++,先++,再使用
int d = a--;//后置--,先使用,再--
int e = --a;//前置--,先--,再使用
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
③!逻辑反操作 (真变成假,假变成真,0为假,非0为真)
int main()
{
int a = 0;
int b = !a;
printf("%d\n",b);判断为真时系统默认打印1
int a = 10;
if(a) a为真时,打印hehe
{
printf("hehe\n");
}
if(!a) a为假时,打印hehe
{
printf("hehe\n");
}
return 0;
}
④&和*取地址操作符和解引用操作符
int main()
{
int a = 10;
int* p = &a;在这里就是取变量a的地址,这里的p实际上就是一个指针变量,*表示这是一个指针,p是一个变量由于存储变量a的地址,int说明这个指针指向的是一个int型的数据。
*p = 20; 此时的*是解引用操作符,用过p地址得到20,此时的a就变成20
int arr[10] = {0};
arr;表示数组首元素的地址
&arr[0];表示取数组首元素的地址
&arr[9];表示取数组第十个元素的地址
&arr;表示取数组的地址
}
⑤ ~ 按位取反操作符
int main()
{
int a = 0;
//00000000 00000000 00000000 00000000
int b = ~a;
//11111111 11111111 11111111 11111111在这里,二进制所有数按位取反,包括符号位。
printf("%d\n", b);
//补码:11111111 11111111 11111111 11111111
//反码:11111111 11111111 11111111 11111110
//原码:10000000 00000000 00000000 00000001
return 0;
}
后面会继续发表有关后面其他操作符的理解,作为一个C语言的初学者,这算是我的第一篇博客,也是浅显的谈了一下我对于操作符的理解和认知,欢迎大佬批评指正!