目录
3.sizeof(计算变量或者类型所占空间的大小,单位是字节)
1.&&(逻辑与)(再三强调:在C语言中,0为假,非0为真)
前言:
最近不知道怎么回事,突然就没了学习的动力,原本打算昨天下午写的,一直鸽到现在,最近我会慢慢找回状态的,昨天科目二也过了,最近几天我会保持每天至少一篇博客的。
我也就废话不多说,进行接下来的讲解——操作符。
介绍:
- 算数操作符:+(加号) -(减号) *(乘号) /(除号) %(取模)
- 移位操作符:>> (右移) <<(左移)
- 位操作符:&(按位与) |(按位或) ^(按位异或)
- 赋值操作符:= += -= *= /= $= ^= |= >>= <<=
- 单目操作符:!(逻辑反操作) -(负值) +(正值) &(取地址) sizeof(操作数的类型长度,以字节为单位) ~(对一个数的二进制按位取反) ++ -- *(间接访问操作符/解引用操作符) (类型)(强调类型转换)
- 关系操作符:>(大于) >=(大于等于) <(小于) <=(小于等于) !=(不等于) ==(等于)
- 逻辑操作符:&&(逻辑与) ||(逻辑或)
- 条件操作符:exp1 ? exp2 : exp3(也叫三目操作符)
- 逗号表达式:exp1, exp2, exp3, ... ,expN(用逗号隔开的表达式就是逗号表达式)
- 下标引用,函数调用操作符:[ ] ( )
一.算数操作符
加减乘除我就不过多介绍,算数操作符我就简单介绍一下除号(/)和取模(%)之间的区别
区别:/是用来取商而%是用来取余数
例析:
#include<stdio.h>
int main()
{
int a=5/2;
printf("%d\n",a);
return 0;
}
#include<stdio.h>
int main()
{
int a=5%2;
printf("%d\n",a);
return 0;
}
总所周知:5➗2=2……1
因此第一个代码输出的结果应该是2(商),第二个代码输出的结果应该是1(余数)
二.移(二进制)位操作符:
1.先简单介绍一下十进制和二进制之间的转换规律(用电脑打字解释起来有点费劲,就直接手写了,如果还不能理解可以私信问我)
(我也不知道为什么会是这样,就将就着看一下吧)
2.例析(以在<<为例,>>同理)
#include<stdio.h>
int main()
{
int a=1;//整型1占4个字节——32个bit位
//因此1用二进制表示应是:00000000000000000000000000000001(不用数了,一共32位)
int b=a<<1;//a向左移了一位之后: 00000000000000000000000000000010(十进制表示为2)
printf("%d\n",b);
return 0;
}
输出结果:2
思考:如果在上面代码的基础上再顺手打印一下a,那么a的值是几呢?
答案是:1
相当于你移位之后原来a的值是不变的(除非移位之后再将值赋给a),你打印的b是a移位之后的值,a还是原来的a
三.(二进制)位操作符
补充:规定0为假,非0为真
1.&(按位与)
#include<stdio.h>
int main()
{
int a=3;//3转化为二进制是011
int b=5;//5转化为二进制是101
int c=a&b;//a:⬇011(0为假,非0为真),从上往下对应着看
//b:⬇101
//c: ⬇0(0和1按位与为0)0(1和0按位与为0)1(1和1按位与为1),所以c的二进制数为001,打印的结果是1
printf("%d\n",c);
return 0;
}
输出结果:1
总结:
&:0和1为0,1和1为1,0和0为0
2.|(按位或)
#include<stdio.h>
int main()
{
int a=3; //011
int b=5; //101
int c=a|b; //111
printf("%d\n",c);
return 0;
}
输出结果:7
总结:
|:1和1为1,1和0为1,0和0为0(只要与一个1结果就是1)
举个例子:你早上要吃早饭,现在有a套餐和b套餐,你只要选则其中一种,吃早饭这一项任务就完成了(当然a,b套餐都吃也可以)
3.^(按位异或)
(不是次方的意思)
#include<stdio.h>
int main()
{
int a=3; //011
int b=5; //101
int c=a^b; //110
printf("%d\n",c);
return 0;
}
输出结果:6
总结:
^:对应二进制位相同,则为0;对应二进制位相异,则为1
四.赋值操作符
a=20;(=是赋值,==是判断相等)
a=a+10;可以写成:a+=10;
a=a-10;可以写成:a-=10;
a=a&2;可以写成:a&=2;
……(其他同理)
五.单目操作符
(也有双目操作符,三目操作符,区别在于操作数的不同,单目操作符有一个操作数,双目操作符有两个操作数,三目操作符有三个操作数)
1.!(逻辑反操作)
(c语言中0表示假,非0为真)
#include<stdio.h>
int main()
{
int a=10;
printf("%d\n",a);
printf("%d\n",!a);
return 0;
}
输出结果:10
0
解释:10为非0,因此为真,而!a则会将真变为假,及将10变为0
思考:如果a=0,那么!a=?
结果:1
解释:0为假,!a则将假变为真,在假变为真时,只会变为1
2.+和-
用来表示正数和负数
3.sizeof(计算变量或者类型所占空间的大小,单位是字节)
#include<stdio.h>
int main()
{
int a=10;
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(int));
return 0;
}
输出结果:4
4
注意:sizeof计算变量时可以省略括号,但计算类型时不能省
计算数组大小:
#include<stdio.h>
int main()
{
int arr[10]={0};
printf("%d\n",sizeof(arr));
return 0;
}
输出结果:40
计算数组的元素个数(个数=数组总大小/每个元素的大小)
#include<stdio.h>
int main()
{
int arr[10]={0};
int sz=0;
printf("%d\n",sizeof(arr));
sz=sizeof(arr)/sizeof(arr[0]);
printf("sz=%d\n",sz);
return 0;
}
输出结果:40
sz=10
4.~(二进制按位取反)
补充:
- 源码,反码,补码
- 只要是整数(分正整数和负整数),内存中存储的都是二进制的补码
- 正数的源码,反码,补码相同
- 有符号的整型的最高位表示符号位(红色数字),如果为1表示负数,为0表示正数
- 例(a和b与下面代码中的a和b相同): a=00000000000000000000000000000000(最高位为0,表示正数) b(有符号的整型)=11111111111111111111111111111111(最高位为1,表示负数,为补码,而打印的是这个数的源码)
- 源码符号位不变,其他位按位取反得到反码,反码加一得到补码
- 例1:补码:11111111111111111111111111111111 反码:11111111111111111111111111111110 源码:1000000000000000000000000001(1表示负数,因此得到-1)
- 例2:-2 十进制 10000000000000000000000000000010 源码 11111111111111111111111111111101 反码 11111111111111111111111111111110 补码
#include<stdio.h>
int main()
{
int a=0;//4个字节,32个bit位
int b=~a;
printf("%d\n",b);
return 0;
}
输出结果:-1
5.++和--
#include<stdio.h>
int main()
{
int a=10;
int b=a++;
printf("a=%d b=%d\n",a,b)
return 0;
}
输出结果:a=11 b=10
#include<stdio.h>
int main()
{
int a=10;
int b=++a;
printf("a=%d b=%d\n",a,b)
return 0;
}
输出结果:a=11 b=11
解释:
后置++:先将a的值赋给b,因此b为10,再将a++,所以a为11,即先使用,后++
前置++:先将a++,a的值变为11,再将a的值赋给b,因此b的值也为11
--同理
6.(类型)
#include<stdio.h>
int main()
{
int a=(int)3.14;
return 0;
}
如果没有(int)会有警告,因为int是定义整数变量,而3.14是小数,应该使用double类型,但如果你就想这样使用,可以加(int)进行强制类型转换(将double类型转换成int类型),这样就不会报错了
7.&(取地址操作符) 和*(解引用操作符)
#include<stdio.h>
int main()
{
int a=10;
printf("%p\n",&a);//可以打印出a所在的地址,%p用来打印地址,打印出来的是十六进制的,结果是随机的
return 0;,
}
#include<stdio.h>
int main()
{
int a=10;
int* p=&a;//int*是指针变量的类型,p为指针变量,该代码的目的是将a的地址存放在p中
printf("%p\n",&a);
printf("%p\n",p);//输出的两个结果是一样的
*p=20;//*是解引用操作符,*p是指对p进行解引用操作,找到它所指向的对象a,*p=20是指将通过*p找到的a的值改为20
printf("a=%d\n",a);//打印出的a的值应为20
return 0;,
}
解释:
int a=10;定义了一个变量a并赋值10,a的地址为0x0012ff40
int* p=&a;将a的地址放到p当中
*p=20;将a中的10改为20
这个是计组里的间接寻址方式,在这里不理解也没事,先了解一下,之后还会详细讲解的
六.关系操作符(略)
七.逻辑操作符 (与位操作符相似)
1.&&(逻辑与)(再三强调:在C语言中,0为假,非0为真)
#include<stdio.h>
int main()
{
int a=3;//3为真
int b=5;//5为真
int c=a&&b;//真&&真为真,并且定义真为1
printf("c=%d\n",c);
return 0;
}
输出结果:c=1
总结:
- &&:真&&真为真,真&&假为假,假&&真为假,假&&假为假
- 定义如果为真则结果为1,如果为假则结果为0
2.||(逻辑或)
#include<stdio.h>
int main()
{
int a=0;//0为假
int b=5;//5为真
int c=a||b;//假||真为真,并且定义真为1
printf("c=%d\n",c);
return 0;
}
输出结果:c=1
总结:
在||中,只要有一个为真结果就为真
八.条件操作符
exp1 ? exp2 : exp3(exp1,exp2,exp3是表达式的意思)(三目操作符)
#include<stdio.h>
int main()
{
int a=10;
int b=20;
int max=0;
max = (a > b ? a : b);
printf("max=%d\n",max);
return 0;
}
输出结果:max=20
解释:
- max=(a>b?a:b);表示如果a>b成立,则将a的值赋给max,如果不成立,则将b的值赋给max
- 即如果?前的exp1成立,则输出exp2,如果exp1不成立,则输出exp3
补充另一段代码,和条件操作符相似:
#include<stdio.h>
int main()
{
int a=10;
int b=20;
int max=0;
if (a>b)
max=a;
else
max=b;
printf("%d\n",max);
return 0;
}
输出结果:20
解释:
这段代码使用if,else语句,也可以起到和条件操作符相同的作用,但相比之下,条件操作符较为简单
九.逗号表达式
解释:用,隔开的表达式即为逗号表达式
十.下标引用,函数调用和成员结构操作符
1.[ ](下标引用操作符)
#include<stdio.h>
int main()
{
int arr[10]={0};
arr[4];//[ ]为下标引用操作符,在上一篇文章讲解整型数组中有讲过,[4]为访问下标为4的元素
return 0;
}
2.( )(函数调用操作符)
#include<stdio.h>
int add(int x,int y)
{
int z=0;
z=x+y;
return z;
}
int main()
{
int a=10;
int b=20;
int sum=add(a,b);//( )调用前面定义的函数,因此叫函数调用操作符
return 0;
}
致读者:
第一次写这么长的文章,真的只有自己经历过才知道那些博主写大几千甚至上万字的文章是多么厉害,我之前并没有打算写长文章,甚至写这篇文章时有想过分成几篇发表,因为我知道在现在快节奏的时代里很多人都不能静下心来去读一篇文章。我本人之前就是,遇到长文章就难以静下心来,快速滑倒评论区,草草看一下评论便离开了,自己当时甚至会有一种满足感,就仿佛文章都理解了一样,但到头来都是自我满足,也是人们常说的假努力,看似浏览过很多文章,但没有几篇是认真去理解的,这样最终的后果便是陷入焦虑当中,越焦虑便越难以静下心,以此往复,陷入了死循环。短文章或许能适应快节奏,但一定不是我们想要的,如果连一篇长一点的文章都读不下来,那我们拿什么和别人比呢?又拿什么去谈我们的理想呢?
但写完这篇之后我便明白了写长篇文章真的需要花费很多精力,博主为了写好一篇文章,花费了大量时间和精力,为的是什么?难道不是为了读者能更系统的理解吗?
短文章适合碎片化的阅读,而长篇文章则需要我们全身心投入才行,但我们学编程不就是需要全身心投入吗?
如果说现在的是带节奏是一列火车,我们为了跟上它,拼尽全力去奔跑,不顾路途的美景,仅仅是奔跑,那么最终我们只会筋疲力尽,因为我们是人,我们要避免精神内耗,避免无谓的焦虑。我们只有在奔跑着尝试着接受周围的美景,适当放慢脚步,去调整呼吸,去改正错误,在一次次跌倒中去战胜自我,去吸取教训,这样我们才能跑的更稳,更快,更远。
以上仅仅是我写完这篇文章的感悟,希望能给你们一些启发和帮助。
最后的最后:
因为第一次写长篇文章,难免会犯些错误,希望能够指正,另外有什么好的建议以及问题可以在评论区互动。