C语言初级<操作符>

发布于:2022-12-22 ⋅ 阅读:(457) ⋅ 点赞:(0)

前言

C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。

本篇文章是基于C语言,对入门小知识操作符的讲解,展示平台为Visual Studio,所有操作符的输入都是在英文输入法下进行输入。文章较长,请耐心观看!

108f8c2cda434f798804b85eb99ecbc3.gif


目录

前言

正文部分

1.  算数操作符

1.1 算数操作符+

 1.3 算数操作符*

1.4算数操作符/

2.  移位操作符和位操作符

2.1  移位操作符

2.2  位操作符

 3.  =赋值操作符

3.1  =直接赋值

3.2  复合赋值

3.3 其他特殊操作符间接赋值

4.  单目操作符

4.1  !逻辑反操作符

4.2  +正值

4.3  -负值 

 4.4  &取地址和*解释引用

4.5  sizeof操作数的类型长度

4.6  ~二进制位反制符

4.7  前,后置++ 

 4.8  前后置--

4.9  (类型)强制类型转换

5.  关系操作符

5.1  大于>和小于<

5.2  大于等于和小于等于

5.4  ==等于

 6.  逻辑操作符

6.1  &&逻辑与

6.2  ||逻辑或

7. 条件操作符

8.  逗号表达式

9.  下标引用,函数调用以及结构成员符

9.1  [ ]下标引用符

10.  关于操作符的其他规则

 10.1  关于数值计算时值型的转换

 10.2   操作符的优先级

说在最后



正文部分

1.  算数操作符

C语言中的算术操作符有

+加,-减,*乘,/除,%除余

  

1.1 算数操作符+

加号大家应该都不陌生,其实在C语言中加号的使用方法非常单纯,就是相加,例如1+1=2。

27e02dbcc41b427b958df522a928a76e.png
图1  算数操作符+

1.2 算数操作符-

减号的使用与加号相同,也是单纯的相减。

397cf90e115f447aa8ddab394a8ac3b7.png
图2  算数操作符-

 1.3 算数操作符*

*号在生活中可能不常见,它代表的是乘号,即"X",但由于C语言的定义,在编译器中,*为乘号。它的使用也比较简单,就是相乘。

20e050084a4c4243a2601201f56e2f1a.png
图3  算术操作符*

1.4算数操作符/

/号在生活中也很少见,多见于部分手机计算器中,/在C语言中是除号➗,但C语言定义/是除的意思,但/除号在C语言中的用法却很讲究,特别是整型和浮点型值涉及小数的计算,是不同的。

1.4.1  首先是简单的整除

2bc70a520a94412bbf7adea66895268b.png
图4  算术操作符/简单整除

1.4.2  不能整除的情况

4f5c09e7f7fb4959968f5010ee284461.png
图5  算术操作符/不能整除的情况

可以看出,7/2应该是等于3.5的,可是输出的结果却是3。

那么是什么原因呢?在C语言编译器中,对于整型值的整除,由于值是整型,编译器输出时会向零取整。所以,即便是3.99,编译器仍会输出3。

我们变换一下定义方式,用浮点型进行定义和计算。

36c9e15395c948419211f58023c1e216.png
图6  算术操作符/浮点型整除

可以发现,转换为浮点型之后,计算的值带有小数,且为3.5,说明值的计算与定义的值类型非常重要。

但在后面的研究中,我又发现了一个情况,及时定义了浮点型也输出3。

77cf11fdd74048f1aa741c41284e9777.png
图7  算术操作符/浮点型整除它例

 那这是为什么?

这是因为计算机在计算时,是先计算右值再赋给左值a,所以先计算的值取整为3,所以输出3.000000。我们只需要让计算机知道数为浮点数,再计算就可以了。

2cefbece1b5146ecaa3824243e6067e1.png
 图7  算术操作符/浮点型相除

1.5  算数操作符%

%在生活中是百分比的意思,但在C语言中%的意思是除余,有些整数相除不能得到整数,例如刚刚所示例的7/2,除余就是一直相除,除到剩下的值无法再除时输出这个无法相除的值,这个值就是余数。例如7/2>5/2>3/2>1/2,其中,最后1/2无法整除,编译器便会输出1。

a13030ee29514ed9bec61797fc84faca.png
图8  算术操作符%

这里要说的是,%只能对整数除余,如果定义float浮点型,编译器会报错。


2.  移位操作符和位操作符

这两种操作符都是非常底层的,对二进制代码进行操作,此处只是大概介绍一下功能,以后有机会,借例子着重介绍。

2.1  移位操作符

位移操作符分为:

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

2.1.1  右移操作符>>

>>表示将值的二进制码向右移位。

6a275045f56a476f94321c36966ec1f1.png
图8  右移操作符

 原理讲解:

由于a是整型,在VS编译器中,VS属于64位软件,所以a占4字节,4B=32bit,二进制就是32位。

则a的二进制存储结构为000000000000000000000000000010。

图中a>>1表示a的二进制编码向右移1位,当然a>>2就是移位。

若向右移一位则结构为000000000000000000000000000001,1后的0被消除掉,前面开头空出来的一位用0补齐(第一个数为符号位,0位正数,1位负数),由二进制算法,a目前是1。

  

2.1.2  <<左移操作符

 <<表示将值的二进制码向左移位。

1ed302b719d246b892476e0c21004340.png
图9  左移操作符

 原理与右移相同,向左移一位, 000000000000000000000000000100,开头消除一个0末尾由于空缺,补上一个零,由二进制算法,a目前是4。

原理简图:

e394365f8c694539b1a0bf29afca5713.png
图10  移位操作符原理

2.2  位操作符

位操作符这里介绍的有三个,分别是:

&按位与,|按位或,^按位异或

这三个操作符都是对值的二进制数进行计算,前面我们已经提到过,在编译器中,一个整型值的二进制数是32位,所以是对这32位数进行操作运算。


2.2.1  &按位与的运算原理

该运算是将两数的二进制为进行运算,当两数二进制位都为1时,保留该位上的1,否则为0,

即1&1=1,1&0=0,0&0=0;这样说比较抽象,我们进行示例:

75652f3efc5348c09d67fc0f6fd28f53.png
图11  按位与操作符代码示例

 原理如图:

d0037794a747431b9d7fe08a89a440f7.png
图12  按位与原理图解

 2.2.2  |按位或的运算原理

|按位或的运算与按位与相反,当两数二进制位都为0时,保留该位上的0,否则为1。即1|1=1,0|1=1,0|0=0;我们还是先上图:

68704a796a3d4513a779bf2e3dee21d9.png
图13  按位或操作符代码示例

原理如图:

df5619ecbd4a4245967e661e57fbf122.png
图14  按位或原理图解

2.2.3  ^ 按位异或的运算原理

^按位异的运算与前两个操作符不同,该操作符是两个数的同一个二进制位,相同为0,不同为1。

即1^1=0,0^0=0,1^0=1;代码示例:

52e5082e8c6e42008a60c5e0b854a771.png
图15  按位异或操作符代码示例

 原理如图:

925fa8af7e5446e4a28b2a3b1840c74e.png
图16  按位异或原理图解

 3.  =赋值操作符

赋值操作符=是给定义的变量进行赋值,如果只使用=,那么就是直接赋值;

还有一些赋值是搭配其他操作符进行运算后再进行赋值:

+=自增赋值,-= 自减赋值,*=自乘赋值,/=自除赋值,%=自除余赋值

其中,还有一些特殊操作符的使用我们已经介绍过了:

&=按位与赋值,^=按位异或赋值,|=按位或赋值,>>=右移后赋值,<<=左移后赋值

在与赋值操作符一起连用时,我们会对知识点进行补充以代码运行结果的形式展现。

3.1  =直接赋值

3.1.1  赋值数值

3.1.1.1  整型常量直接赋值

9d9d768b4ae2416ab6185d35b7d9d083.png
图例  整型常量直接赋值

 将整型常量1直接赋值给整型变量a。

3.1.1.2  浮点型常量直接赋值

97d1ff47fe314a50ac0fff578743685f.png
图17  浮点型数值直接赋值

将浮点型常量1.5直接赋值给浮点型变量a。


3.1.2  赋值字符

3.1.2.1  字符型常量直接赋值

82e8bdd07ccf42099866637b0ce8623b.png
图18  字符型常量直接赋值

将字符型常量‘C’直接赋值给字符型常量a。

  

 3.1.2.2  字符串常量直接赋值

b4c17ba8ea334d099471d5e1019031e7.png
图19  字符串常量直接赋值

 将字符串常量“CSDN”直接赋值给字符型数组a[5];


3.2  复合赋值

3.2.1  +=自增赋值

8dfd842bb9f945c9ac745659834f5dba.png
图20  自增赋值

如图20,a+=1相当于a=a+1。

  

 3.2.2  -=自减赋值

751a9c354faf49d6bff7ced6de9ebb7c.png
图21  自减赋值

如图21,a-=1相当于a=a-1。

  

 3.2.3  *=自乘赋值

b39e3a724959404aba1a836d2ad941a0.png
图22  自乘赋值

 如图22,a*=2相当于a=a*2。

3.2.4  /=自除赋值

c2b1ae336f44493ea2ea8388de12bae4.png
图23  自除赋值

 如图23,a/=2相当于a=a/2。 

  

3.2.5  %=自除余赋值

e706dd48006d484e985e60a136d87100.png
图24  自除余赋值

  如图24,a%=2相当于a=a%2。 

  

3.3 其他特殊操作符间接赋值

3.3.1  &=按位与赋值

bf722c5c17a64d5085658535928a599b.png
图25  按位与赋值

   如图25,a&=2相当于a=a&2。 

3.3.2  |=按位或赋值

16f820a3cba846bea0407a7e586a0739.png
图26  按位或赋值

 如图26,a|=2相当于a=a|2。

  

3.3.3  ^=按位异或赋值 

5829c8b303f04d4a9e0a5dfa79fa4206.png
图27  按位异或赋值

  如图27,a^=2相当于a=a^2。

3.3.4  >>=右移操作符赋值

8c8c72216ecf4125b6736beff76164a2.png
图28  右移操作符赋值

 如图28,a>>=2相当于a=a>>2;这里要提醒的是,a>>2表示二进制位向右移动两位。

3.3.5  >>=左移操作符赋值

62ca8fe7c698417199bca1ac4f0f3791.png
图29  左移操作符赋值

 如图29,a>>=2相当于a=a>>2;这里要提醒的是,a<<2表示二进制位向左移动两位。


4.  单目操作符

单目操作符有:

!逻辑反,+正值,-负值,&取地址,sizeof操作数的类型长度,~对二进制位反制,

前后置++,前后置--,*解引用操作符,”(类型)“强制类型转换


4.1  !逻辑反操作符

反逻辑操作符就是是否变换,是变不是,逻辑反制 

1f6262635f9743bf8481ac0a1096235a.png
图30  逻辑反操作符

如图30, 第一个if我们的条件中放的是非i,我们定义i=0,非i就是非0,if判断语句的判断条件是1为真,执行语句,否则为0即为假,跳过执行,这里要说的是,并非判断条件一定是1,当输入数值大于1是也成立。当我们再次给i进行赋值,执行结果与!1的一样,表示!操作符将i的值反值为非0,那if语句就成立了,所以!是将逻辑反制,一般在if判断依据和while循环语句中常用,以后会详细介绍。


4.2  +正值

顾名思义,就是让值为正。

95fe99256c024ef2a699b123246f21d5.png
图31  正值

编译器默认正值省略+符号!


4.3  -负值 

顾名思义,就是让值为负,当然也可以负负为正。

d3fb2963467a44438bef1b38f5e62dd3.png
图32  负值

 4.4  &取地址和*解释引用

大家可能看到&符号想到了前面的按位与,但&符号还能取地址,大家知道C语言是所有语言中比较底层的语言,可以通过指解释引用符*也就是针访问地址,顾名思义,取地址符&就是获取某个变量的内存地址,常与解释引用符*指针连用,后面会详细介绍,这里做简单讲解。

c0e2832ddc564eef8be641beb454f8d7.png
图33  取地址符和解释引用符

 如图可以发现,通过取地址符,将获取的地址赋值给解释引用变量*b(指针*b),然后输出,若单独输出b则是输出b所存放的a的地址,如果加上解释引用符,则是输出指向地址存放的值地址,即b=&a=10091628,*b=a=0。


4.5  sizeof操作数的类型长度

sizeof操作符以字节形式给出了其操作数的存储大小,操作数可以是一个表达式或括在括号内的类型名,操作数的存储大小由操作数的类型决定。 

f3039ac715ba4886850f35b0150a60c6.png
图34  操作数的类型长度

 由图34,可以发现,整型int的类型大小为4,也就是分配的内存空间为4字节,而字符型char的类型大小为1

在定义数组时,我们又发现,如果对数组名求类型大小,那么输出的是整个数组的类型大小,且单个元素的类型大小等于一个整型的类型大小,字符型也一样,字符型数组单个元素的类型大小等于单个字符型变量的类型大小。

所有sizeof是求操作符的类型大小,也可以说是所分配的内存空间大小。


4.6  ~二进制位反制符

~是用来对一个二进制数按位取反,即将0变1,将1变0。

37d1336827c84778878466f1cddf0158.png
图35  二进制位反制符

原理图解:

cab772e10af84269ba8a87a7522a3745.png
图36  反制操作符原理

4.7  前,后置++ 

先上代码:

2a1f161c7af843858753ff9299072983.png
图37  前后置++

 如图,可以发现,前置++是先计算k+1再赋值给a,所有赋给a的值是2;而后置++则是先将值传递赋给b再计算i+1,所以前后置++在使用时需要考虑逻辑。


 4.8  前后置--

原理与前后置++相同,不多说,我们直接示例:

91c2120ac83a45d7af83e555abcb8a28.png
图38  前后置--

4.9  (类型)强制类型转换

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int Π = 3.14;
	return 0;
}

 对于一个整型变量Π,如果我们强行赋值给它一个浮点型变量3.14,那么部分编译器会报错!

"“初始化” : 从“double”转换到“int”,可能丢失数据";

所以,我们需要强制类型转换来解决这个问题:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int Π = (int)3.14;
	return 0;
}

如上代码段,对值进行(int)3.14后,值就被强行转换为3(C语言向零取整)。


5.  关系操作符

关系操作符在判断语句中常用,用来构成一定的逻辑,主要有:

>大于,小于<,>=大于等于,<=小于等于,!=不等(非等),==等于

5.1  大于>和小于<

顾名思义,<和>与平常生活中理解相似,也就是大于小于,但在编程中常用于逻辑判断,如: 

245b666a770f4827b49427e786c8ac71.png
图39  大于小于

5.2  大于等于和小于等于

顾名思义,在大于小于的基础上,包含了等于,如果值相等也满足条件,如:

645b95a157294b75ac834898b37d260c.png
图40  大于等于和小于等于

5.3  !=不等 

顾名思义,!=就是不等于的意思,例如:

332ab8569afb4ddca9854b97acf5d75d.png
图41  不等

 如图,当我们输入非2的数时,编译器判断成立。


5.4  ==等于

首先,在C语言中=是赋值,而双等于号才是等于,但没有赋值的功能,顾名思义,==就是等于,只不过一般是判断两个值是否相等,如:

e02a4b306edd4d18a482260ab2b0ad37.png
图42  等于

 6.  逻辑操作符

C语言中逻辑操作符有:

&&逻辑与和||逻辑或

这里我们需要先与按位与和按位或区分一下,按位与&与逻辑与&&以及按位或|和逻辑或||有相同的地方;不过按位与和按位或是对数值的二进制位进行改变,而逻辑与和逻辑或常用于逻辑判断。

6.1  &&逻辑与

对于逻辑与,我们举个很简单的例子,在逻辑判断中,例如if,1为真0为假,那么逻辑与则是1&&1=1,1&&0=0,0&&0=0,也就是说,很多时候我们的判断条件有两个,我们需要两个条件都满足才执行下面的语句,所以两个条件任何一个不满足则为0。 

3dfddbbf4e5d4e67adb8580712425031.png
图43  逻辑与

可以看出,左图中只满足a>10条件而不满足b<10的条件,所以判断不成立;右图满足a>10和b<10的条件所以判断成立。

  

6.2  ||逻辑或

对于逻辑或,有一点与逻辑与相反,从字面意思可以理解,或就是条件一或者条件二满足一个都可以,事实也确实如此,逻辑或是1||0=1,1||1=1,0||0=0,可以发现,当所有条件不满足时才为假,有一个条件成立则为真。即:

97588660831d49bbad6da8ee4663fe15.png
图 44 逻辑或

可以发现, 左图中a条件不满足,但满足b条件,if判断仍然为真,但右图中,ab条件都不满足,所有判断为假。


7. 条件操作符

格式为:

(条件语句)?(语句1):(语句2)

那么这是什么意思呢?我们先上一段代码和运行结果:

3befc39fd5bf42bf86914519a006d1e1.png
图45  条件操作符逻辑示例

 从图45中可以发现,当输入的数满足a>5的条件if就判断执行为真的语句,那么我们修改一下,用条件操作符的形式来写,如图:

07fddbd621794d07b19866b6e8d38cb9.png
图46  条件操作符示例

 从图46的运行结果中,大家应该知道了条件操作符的大概用处了,也是做判断,问号?号前面是条件,类似于if()括号里面也是放的条件语句,但是,若条件成立,则执行语句1,也就是冒号前(问号后)的语句,如果不成立则执行冒号后的语句,也就是语句2。

条件操作符在日常使用的地方非常多,小到返回一个数,大到调用函数甚至更多!

03df888a3b5f40f1872b9d80d1624dc0.png
图47  条件操作符调用函数(左)和返回数值(右)

 这些在后面会慢慢详细介绍。


8.  逗号表达式

表达式1,表达式2,表达式3,......表达式n

这里要先提及的是,逗号表达式在使用时一般用括号括起来,这样理解起来也很方便:

(表达式1,表达式2,表达式3,......表达式n)

逗号在编译时很常用,但什么是逗号表达式呢?逗号表达式就是用逗号隔开的多个表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。即:

e860040f118e44b7bf2171274bcf6d83.png
图48  逗号表达式

 如图48,可以发现,在逗号表达式中,首先a++,a=2,然后i=a+1=3,最终k=i+1=4,b取最后一个表达式的运算结果,即4。这里先只进行简单的介绍,后面有更复杂的用法再详解!


9.  下标引用,函数调用以及结构成员符

[]下标引用,()函数调用,结构成员符->和‘.’

9.1  [ ]下标引用符

什么是下标?下标出现与数组,我们在定义数组时会在[ ]中放入需要的元素个数,在定义好以后,每一个元素都有一个下标,例如arr[0],arr[5]...等,数组下标一般从0开始,如果我们存入若干个元素,要取出某个元素,则要使用下标取出数组中对于的元素,即:

ee4b5c65c9534cbdb42b433aa0798ce9.png
图49  下标引用符

这里要说的是,数组的下标是从0开始的,最后一个下标不能存储元素而是放入一个’\0‘,用来表示已经到数组末尾。

ee9cecd6ba2a4b6f926e82305b2003f5.png
图50  数组详图

9.2  ()函数调用

我们知道在编程中不会只有一个主函数去运行,那样会显得非常杂乱,各种各样的功能会分成不同的函数去执行,由主函数去调用,那么函数的调用就涉及函数调用的符号();上代码:

974e72bb17da432fbf362aceadb8f9da.png
图51  函数调用

从图中可以发现,函数调用()主要是传递参数!当调用的函数不需要传递参数,括号中可以为空。

  

9.3  结构体成员访问符 -> 和 ‘.’

结构体类型变量可以通过“结构体变量名 结构体成员名”访问;

也可以通过指针,“结构体变量名->结构体成员名”访问。

d481f6f0823d4e74880308dfda8939d4.png
图52  结构体成员访问

10.  关于操作符的其他规则

 10.1  关于数值计算时值型的转换

数值在进行计算时如果遇到不同的值类型的数值进行计算,就会涉及值类型的转换问题,通常优先级是:

6a013fd2d80043b7a2197d014848b1d8.png
图53  数值转换优先级

  

 10.2   操作符的优先级

操作符的属性分为:“操作符的优先级 ”,“操作符的结合性”,“是否控制求值顺序”。

当两个操作符一起使用时,具体先执行哪一个,需要看操作符的优先级,如果两个操作符处于同一级别,那么则看操作符之间的结合性!


说在最后

以上就是本次文章的所有内容!如内容有误,请在评论区留言,欢迎大家交流!

同时感谢各位的耐心阅读,能看到这里的小伙伴们应该都是学霸啦! 

对于C语言入门,这些基本知识还是非常重要的,就像英语的学习,日积月累。

目前自己的水平也处于入门阶段,希望以后能更加深入学习,写出更好的文章贡献给大家。

最后希望跟我一样处于入门阶段的同学们一起共同进步,水平蒸蒸日上。

590ea9bdc1b1421b80b132f372431608.jpeg

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到