操作符分类
我们C语言中的操作符有下面几类:
- 算术操作符
- 移位操作符
- 位操作符
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 条件操作符
- 逗号表达式
- 下标引用、函数调用和结构成员
算术操作符
算术操作符是比较简单的操作符了,我们其实几乎天天见了
: + 、- 、* 、/ 、%
就是我们常见的加 减 乘 除 取模(也叫取余),关于加减乘除这里就不再多说,重点强调一下后两个,我们直接来看代码:
#include<stdio.h>
int main()
{
//两边都是整数,计算得到的也是整数
int i = 10 / 3;
printf("i=%d\n",i);
//除号两边只要有一个浮点数,得到的结果就是浮点数;
//float和double类型默认打印小数点后位;
//想保留几位直接在%f或者%lf前面加.n即可;
double a = 10.0 / 3;
printf("a=%lf\n", a);
double b = 10 / 3.0;
printf("b=%.1lf\n", b);
double c = 10.0 / 3.0;
printf("c=%.2lf\n", c);
//需要强调的是%两边只能是整数(整形);
//所以%得到的值也只能是整数;
int j = 10 % 3;
printf("j=%d\n", j);
return 0;
}
看着其实很简单,但是还是不要偷懒,在强调一次:学编程一定一定一定不要手懒!!!每个代码里面都有很多的小细节,平时不练到用的时候错误百出,手忙脚乱。
移位操作符
移位操作符只有两种:
左移操作符: <<
右移操作符: >>
注:它们的操作数必须是整数
在介绍移位操作符之前我们还要先做一些关于二进制知识上的补充:
我们都知道数字在内存中存储是以二进制的形式存储的,但是还是需要更加细致的了解一下:
从原码到补码的计算过程是我们需要重点掌握的,用一张图来表示,如下:
这里从原码得到补码的过程很好理解,但是从补码返回到原码,一种是怎么来的怎么回去,做相反的操作即可;第二种方法其实补码直接取反,然后再+1,也能得到原码,这其实是计算机当初设计的时候的一个小妙处,可能很多教材并不讲,但是希望大家还是记住,可能使用的时候会方便许多;
好了,关于二进制知识的补充,我们就只做这么多,接下来我们来看我们的移位操作符:
我们说计算机中数字是以二进制补码的形式存储的,当然计算也是移动补码的形式了,我们以10为例
左移操作的执行效果是,左边移动一位丢弃,右边补0;当然这里只是为了方便用这样的一张简单的图来帮助理解,真正在计算机中要复杂的多,牵扯到大小端等等问题,这里只是简单的帮助理解:那么我们来看10向左移动一位的结果:
可以看到我们10左移一位的结果是20;
我们相同的方法,来看一下-10,
结果是-20,由此我们也可以看出一点东西,就是一个数左移1的结果其实就是2倍;那么右移呢?
右移其实和左移还不太一样,我们还是画图还解释:
右移操作其实是分算术右移和逻辑右移,具体是哪一种要取决于编译器,但是通常情况下大多数都是算术右移。
我们可以简单验证一下,我使用的编译器是vs2022,
由于**-1的二进制序列是全为1**,如果是逻辑右移我的结果应该是1才对,这里就可以验证出在vs2022中右移算术右移。
另外这里还有一个东西,不要移动负数位!!
总有些人脑洞大开,写出这样的代码:
这是干什么啊,编译器都不知道你想要干什么了!!这种是肯定不支持的。
还有那种向右移动500位的,这种就不要尝试了。一定要在有效范围内好吧。
位操作符
& 按位与
| 按位或
^ 按位异或
注:他们的操作数必须是整数。
位操作符也是针对于二进制来进行运算的。
我们先来看按位与&,
按照这个思路,只要理解了即可;
按位或 | 也同理:
按位异或^:
赋值操作符
赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。
比如:
int weight = 120;//体重
weight = 89;//不满意就赋值
double salary = 10000.0;
salary = 20000.0;//使用赋值操作符赋值。
值得一提的是赋值操作符其实是可以连续使用的,例如:
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int x = 0;
int y = 0;
x = y = a + b;
printf("x=%d y=%d\n",x,y);
//这是执行顺序是什么样的呢?
//其实是
y = a + b;
x = y;
printf("x=%d y=%d\n", x, y);
return 0;
}
我们这里也只是提一下是可以连用的,但是并不推荐,肯定是下面分开写,代码的可读性较好,并且便于调试观察,所以好的代码风格是从一点点的细节来培养的;
复合赋值
- +=
- -=
- *=
- /=
- %=
-
=
- <<=
- &=
- |=
- ^=
此类连等的复合赋值符我们也已经很熟悉了,这样写可以让代码更加简洁。就不再过多介绍了;
单目操作符
- ! 逻辑反操作
- 负值
+ 正值
- & 取地址
- sizeof 操作数的类型长度(以字节为单位)
- ~ 对一个数的二进制按位取反
- – 前置、后置–
- ++ 前置、后置++
- 星号 * 间接访问操作符(解引用操作符)
- (类型) 强制类型转换
这里有许多也是非常常见的,我们重点来解释一下几个,一些特别常见的就简单提一下:
! 逻辑反操作,什么意思呢?我们看代码:
#include<stdio.h>
int main()
{
int i = 0;
scanf("%d", &i);
if (!i)
{
printf("0\n");
}
else
{
printf("1\n");
}
return 0;
}
这段代码重点就是判断部分,如果没有!的话表示i是真就打印0,i是假就打印1;但是由于我们加上一个逻辑反操作,这段代码表达的意思就是变成了i是假就打印0,i是真就打印1。这就是逻辑反操作的作用,转变原来的意思。
正值,负值没什么好说的,就是简单的正负号,正号没有用的地方,基本都省略。
& 取地址,也是经常用的了,当想拿到一个数据的地址时使用这个符号即可。
例如:
#include<stdio.h>
int main()
{
int a = 10;
int* pa=&a;
printf("%p\n",pa);
char m = '*';
int* pb=&m;
char arr[10] = { 0 };
int* pc = arr;
&arr[0];
&arr;
int* p = "abcdef";
return 0;
}
只要是个变量,就都可以取地址。
星号 * 解引用
&通常和*解引用操作绑定使用;
例如:
#include<stdio.h>
int main()
{
int i = 10;
int *pa=&i;
*pa = 20;
printf("%d\n", *pa);
printf("%d\n",i);
return 0;
}
可以看到我们通过解引用操作是可以直接找到i的地址,然后将它修改了值。
sizeof
关于sizeof其实要讲的也不多:
首先sizeof是一个关键字,也是操作符,但是不是函数!不是函数!不是函数!老是有人把sizeof当成函数,记住了不是函数!
关于sizeof用法,我们看下面代码演示:
#include<stdio.h>
int main()
{
int i = 0;
printf("%d\n", sizeof(i));
printf("%d\n", sizeof i);
printf("%d\n", sizeof(int));
int arr[10] = { 0 };
printf("%d\n",sizeof(arr));
printf("%d\n",sizeof(arr[0]));
printf("%d\n", sizeof arr);
printf("%d\n", sizeof (int[10]));
return 0;
}
一般就用于一个数或者数组来计算大小,经常使用sizeof计算整个数组大小除以数组内一个元素大小的方式来计算数组内的元素个数。
另外还有一个需要注意的地方:
#include<stdio.h>
int main()
{
int a = 10;
short b = 5;
printf("%d\n",sizeof(b=a+3));
printf("%d\n",b);
return 0;
}
可以看到b的值是没有改变的,这里**也说明了sizeof内部的表达式是不参与计算的!!!**这点一定要注意,并且还可以看出sizeof计算大小是只看最后的类型。
这里也可以简单解释一下原理:
以上就是对sizeof的详细解释了。
~按位取反
这个操作符也是仅仅针对于整数才可以使用
效果就是将二进制所有位取反
看下面代码:
#include<stdio.h>
int main()
{
int a = 0;
printf("%d\n",~a);
return 0;
}
0的二进制位全部0,而全部取反后结果为全1,所以得到的结果就是-1。
关于++和–
++和–就是简单的自增1或者自减1,只要++或者–后的值就会变化;
需要重点注意的是前置和后置的问题,我们可以举例来说明:
#include<stdio.h>
int main()
{
int i = 0;
int j = i++;
int a = ++i;
printf("%d\n",j);
printf("%d\n",a);
return 0;
}
可以看到我们得到的结果是j=0和a=2;
可以仔细分析一下,这里我们就可以得出结论,前置++代表的是先使用后++,所以j=0;后置++的话就是先++后使用,所以a=2。
当然了对于–也是相同的道理,我们也可以看一下:
#include<stdio.h>
int main()
{
int i = 5;
int j = i--;
int a = --i;
printf("%d\n", j);
printf("%d\n", a);
return 0;
}
可以看到我们的结果就是5,3。好了今天关于操作符先写到这里把,我们下一篇再来解释剩下的操作符。
最后鸡汤:
一个人静静坐在电脑面前写代码的感觉,那是什么感觉?那是武林高手闭关修炼的感觉。