C语言操作符知识点汇总

目录

一. 前言

 二. 各种类型操作符完成的操作

2.1 算数操作符

2.2  移位操作符

2.2.1 左移操作符

2.2.2 右移操作符

2.3 位操作符 

2.3.1 按位与操作符 &

2.3.2 按位或操作 |

2.3.3 按位异或操作符 ^

 2.4 赋值操作符

 2.5 单目操作符(只有一个操作数)

2.5.1 sizeof:操作数的类型长度(字节为单位)

2.5.2  ~:按位取反操作符

 2.5.3  ++、-- 操作符

2.5.4 取地址操作符 &  

2.6 关系操作符

2.7 逻辑操作符

 2.7.2 ||:逻辑或 

2.8 三目操作符 

2.9 逗号表达式(exp 1, exp 2 , ... , exp n)

2.10 下标引用操作符[ ]

2.11 结构体成员访问操作符 .  ->

三.  表达式求值

3.1 整型提升

 3.2 算数转换


一. 前言

在C语言中,每一条指令都有一个或多个操作符,来告诉指令应该进行什么操作。C语言为用户提供了各种类型的操作符来帮助用户完成相应的操作,是C语言程序设计中十分重要的一部分。本文详细汇总了C语言各种操作符的知识点。按照操作符的分类,介绍了不同操作符实现的功能以及表达式求值。从图1.1所示的思维导图可以清晰的看出C语言中操作符的分类以及每种分类下面具体有哪些操作符。C语言操作符知识点汇总_第1张图片

 二. 各种类型操作符完成的操作

2.1 算数操作符

算数操作符较为基础,但应注意整数除法与小数除法的区分、只能对整数取模(对负整数也可以取模)。注意,若要进行小数除法,应将除数和被除数定义为float或double类型,同时将除法操作符左右两边的操作数之一写为小数形式。

//整数除法
int a = 3 / 5;  //运算结果为0,而非0.6
int a = 6 / 5;  //运算结果为1,而非1.2

//小数除法
float a = 6 / 5; //运算结果为1,
//若希望运算结果为1.2,则应将除法运算操作符的两个操作数其中至少一个写为小数形式
float a = 6.0 / 5; //运算结果为1.200000

//取模运算
int a = 7 % 3; //a = 1 
int b = -5 % 2; //b = -1

2.2  移位操作符

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

2.2.1 左移操作符

左移操作符运算规则:高位丢弃、低位补0。 下面举例说明:

如图2.1所示的程序的打印结果为20,该程序进行的操作是将10的二进制序列左移一位,图2.2展示了左移操作的执行原理

C语言操作符知识点汇总_第2张图片 图 2.1 左移一位程序

C语言操作符知识点汇总_第3张图片 图2.2 左移操作执行的底层逻辑

2.2.2 右移操作符

对于右移操作符>>,其存在两种可能的情况:

1.  算数右移:低位舍弃,高位补原来的符号位

2.  逻辑右移:低位舍弃,高位补0

C语言操作符知识点汇总_第4张图片 图2.3 将 a = -1 右移一位

为了验证在集成编译环境VS2019下右移操作执行的是算数右移还是逻辑右移,编写如图2.3所示的程序,该程序进行将a=-1右移一位的操作,由于-1的最高位为1(代表负数),则通过分析该程序,可以得出执行的是算数右移。

C语言操作符知识点汇总_第5张图片 图2.4 a=-1右移一位执行操作的底层逻辑

分析过程如图2.4所示,我们已知整数的二进制序列在内存中存储的是其补码,故对a进行右移一位操作也是对其补码进行,假设高位补0,右移之后得到的二进制序列补码是1111....1111,对应的十进制数为-1,故验证可得此处是在进行算数右移。

这里拓展一些知识:

整型的二进制表示形式有三种:

1.  原码:直接根据数值写出的二进制序列为原码

2.  反码:原码符号不变,其他位按位取反就是反码

3.  补码:反码 + 1,就是补码

2.3 位操作符 

2.3.1 按位与操作符 &

如图2.5所示的实例所示,对二进制序列进行按位与判断,若某一位上两个二进制序列均为1,则输出1,若其中一个为0或两个均为0,输出0。

C语言操作符知识点汇总_第6张图片 图2.5 按位与操作实例

2.3.2 按位或操作 |

如图2.6所示的实例所示,对二进制序列进行按位或判断,若某一位上两个二进制序列其中一个为1或均为1,则输出1,两个均为0,输出0。

C语言操作符知识点汇总_第7张图片 图2.6 按位或操作实例

2.3.3 按位异或操作符 ^

如图2.7所示的实例,按位异或的操作规则是对应的二进制位相同为0相异为1。

C语言操作符知识点汇总_第8张图片 图2.7 按位异或操作实例

 2.4 赋值操作符

复合赋值:+=、-=、*=、%=、^=、<<=、>>=

注意:C语言是支持连续赋值的,但一般不推荐使用连续赋值。如图2.8所示的程序,相当于降y+1赋值给x,再将x赋值给a。打印出的结果为x=11,a=11。

C语言操作符知识点汇总_第9张图片 图2.8 连续赋值

 2.5 单目操作符(只有一个操作数)

2.5.1 sizeof:操作数的类型长度(字节为单位)

sizeof 可以对变量名和变量类型求大小,对变量名求大小是可以省略括号,但对变量类型求大小时不可以省略括号。

int a=10;
printf("%d\n",sizeof(a));
printf("%d\n",sizeof a); //sizeof对变量名求大小可不加括号
printf("%d\n",sizeof(int));//sizeof对变量类型求大小不可不加括号

sizeof可以对数组求大小:

int arr[10]={0};
printf("%d\n",sizeof(arr)); //计算结果为40

//int [10] 即为数组arr[10]的变量类型
printf("%d\n",sizeof(int [10])); //计算结果为40

 在sizeof内部的表达式不参与计算,且有时要进行多余位的截断:

int main()
{
	short s = 5;
	int a = 10;
	printf("%d\n", sizeof(s = a + 2)); //打印结果为2,a+2要放入s,s为短整型,占2个字节,s的空间不会因为a为int类型而发生改变,要进行高位截断
	printf("%d\n", s); //在sizeof内部的表达式不参与运算。这里打印结果为5
	return 0;
}

2.5.2  ~:按位取反操作符

整型变量在内存中存的是其补码,在按位取反操作中也是对整型的补码按位取反,对补码取反后得到的二进制序列就是所求结果的原码。 按位取反操作符对符号位也取反。下面的代码输出结果为4,其执行逻辑如图2.9所示。

int main()
{
	int a = -5;
	int b = ~a;
	printf("%d\n", b);//输出结果为4
	return 0;
}
C语言操作符知识点汇总_第10张图片 图2.9 按位取反原理

 2.5.3  ++、-- 操作符

注意区分前置++(--)和后置++(--)的区别:

前置++:先++后使用     后置++:先使用后++    (-- 操作符同理)

int main()
{
	int a1 = 10, a2 = 10;
	int b = a1++;
	int c = ++a2;
	printf("%d\n", b); //打印10
	printf("%d\n", c); //打印11
	return 0;
}

2.5.4 取地址操作符 &  

通过&操作符,可以将变量存储在内存中的位置提取出来,%p可以用来打印地址(16进制输出),解引用操作符*可以通过访问地址来改变变量的值。

int main()
{
	int a = 10;
	printf("%p", &a); //打印地址用%p,16进制输出
	int* pa = &a; //pa是用来存放地址的 -- pa为指针变量
	*pa = 20; //*为解引用操作符(间接访问操作符),这里为通过访问地址更改a的值。
}

(5)强制类型转换操作符  (类型)

int a = (int)3.1415  //将3.1415强制转换为整型

2.6 关系操作符

主要的关系操作符有:>,<,>=,<=,!=,==

注意:量字符串比较不能用==,应该用strcmp(arr1,arr2)

如果:arr1 < arr2 ,返回值 <0

如果:arr1 > arr2,返回值 >0

如果:arr1 = arr2,返回值 =0

2.7 逻辑操作符

2.7.1 &&:逻辑与       

对于逻辑与操作 exp1 && exp2,当exp1与exp2均为真时,整个表达式为真,否则为假。

 2.7.2 ||:逻辑或 

对于逻辑或操作exp1 || exp2,但exp1与exp2其中之一为真或都为真时,整个表达式为真,exp1和exp2均为假时整个表达式为假。

注意:对于逻辑与操作符,若前面的表达式被判断为假,则不执行后面的表达式。如下面的程序所示,执行该程序打印的结果为1  2  3,因为第一个逻辑与操作符左边的等式(a++)已经被判别为假,所以后面的++b和c++均不执行。

int main()
{
	int a = 0, b = 2, c = 3;
	int i = a++ && ++b && c++;
	printf("%d  %d  %d\n", a, b, c);//打印结果为1 2 3
	return 0;
}

同理,对于逻辑或操作符||,若前面的表达式被判别为真,则不执行后面的表达式。

2.8 三目操作符 

三目操作符仅包含条件操作符,之所以将其成为三目操作符,是因为其有三个操作数。

条件操作符(exp1 ? exp2 : exp3)运行规则:若exp1为真,则执行exp2运行,exp3不运行,整个表达式的值是exp2的值;若exp1为假,则exp3运行,exp2不运行,整个表达式的值是exp2的值。

例:利用三目操作符编写函数求a b中较大的变量:

int max(int a, int b)
{
	return a > b ? a : b;
}

2.9 逗号表达式(exp 1, exp 2 , ... , exp n)

执行规则:从左到右依次运行,逗号表达式最终的结果是最后一个表达式的运行值。

运用逗号表达式可以避免代码过度冗余:

代码1:

a = get_val();
count_val(a);
while(a > 0)
{
   a = get_val( );
   count_val(a);
}

代码2:(改用逗号表达式)

while(a = get_val( ), count_val(a), a > 0)
{
   ;
}

可以明显看出,代码2与代码1等价,但代码2比代码1更加简洁明了。

2.10 下标引用操作符[ ]

用于查找一个数组中的特定元素(数组是通过下标进行访问的)

int arr[5]={1,2,3,4,5};
printf("%d\n",arr[2]);//[ ]为下标引用操作符。打印3

2.11 结构体成员访问操作符 .  ->

结构体成员访问有三种方式:

1. 通过操作符 . (点)直接访问,即:(结构体变量名).(结构体成员名)

2. 通过解引用结构体变量的地址来访问,即:(*结构体指针变量名).(结构体成员名)

3. 通过操作符->,直接应用于结构体指针访问,即:(结构体指针变量名)->(结构体成员名)

下面的代码以定义学生信息结构体为例,通过三种方式访问并打印结构体成员变量:

struct stu  //定义结构体变量
{
	char name[20];
	int age;
	double score;
};
int main()
{
	struct stu s = { "张三",20,89.5 }; //初始化结构体变量

	//直接访问结构体成员变量
	printf("name = %s\n",s.name);
	printf("age = %d\n", s.age);
	printf("score = %lf\n", s.score);
	printf("\n");

	//通过解引用结构体指针访问结构体成员变量
	struct stu* ps = &s;
	printf("name = %s\n", (*ps).name);
	printf("age = %d\n", (*ps).age);
	printf("score = %lf\n", (*ps).score);
	printf("\n");

	//通过操作符->,直接应用于结构体指针访问结构体成员变量
	printf("name = %s\n", ps->name);
	printf("age = %d\n", ps->age);
	printf("score = %lf\n", ps->score);

	return 0;
}

三.  表达式求值

表达式的求值顺序一部分是由操作符的优先级和结合性决定的。同时,操作数要进行相应的类型转换,主要的类型转换有整型提升(隐式类型转换)和算数转换。

3.1 整型提升

以实例来说明整型提升的概念:

char a,b,c;
....
a = b + c;

b、c被提升为普通整型,然后再执行加法运算,加法运算完成后,结果先被截断,在存储于a中。

整型提升的意义:

表达式的运算要在CPU相应的运算器内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int字节长度,同时也是CPU内通用寄存器长度。因此,表达式中各种小于int长度的值,都必须先转换为int类型长度进行运算,然后再截断。

整型提升的过程示例:

int main()
{
	char a = 3;
	char b = 127;
	char c = a + b; //发生整型提升
	printf("%d\n", c); //打印 -126
	return 0;
}
C语言操作符知识点汇总_第11张图片 图3.1

 3.2 算数转换

如果某个操作符的各个操作数属于不同类型,那么要将其中一个操作数转化为另一个操作数的类型,否则操作无法进行。

C语言操作符知识点汇总_第12张图片

操作符相关知识点总结完毕,感谢大家的阅读,敬请批评指正!

你可能感兴趣的:(我的学习之旅,c语言,开发语言)