详解操作符——C语言

发布于:2022-11-07 ⋅ 阅读:(862) ⋅ 点赞:(0)

目录

一、操作符分类

二、讲解操作符

1. 算术操作符

2. 移位操作符

3. 位操作符

4. 赋值操作符

5. 单目操作符 

6. 关系操作

7. 逻辑操作符

8. 条件操作符 (三目操作符)

9. 逗号表达式

10. 下标引用、函数调用和结构成员 

11. 表达式求值

12. 操作符的属性


一、操作符分类

  • 算术操作符
  • 移位操作符
  • 位操作符
  • 赋值操作符
  • 单目操作符
  • 关系操作符
  • 逻辑操作符
  • 条件操作符
  • 逗号表达式
  • 下标引用、函数调用和结构成员

二、讲解操作符

1. 算术操作符

+      -        *        /         % 这个也就是我们所熟知的加减乘除和求模(取余)

  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。% 操作符的两个操作数必须为整数,返回的是整除之后的余数。
  2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要至少有一个是浮点数就执行的是浮点数除法。

举个例子:

 


2. 移位操作符

注:移动的是存储在内存中的补码!(因为整数在内存中存储的是二进制的补码)

<< 左移操作符
>> 右移操作符
   
注:移位操作符的操作数只能是整数。

前言:整形的二进制表示

2.1 左移操作

移位规则:左边抛弃,右边补0

 2.2 右移操作

移位规则:

  1. 逻辑右移:右边丢弃,左边补0
  2. 算术右移:右边丢弃,左边补原符号位

采用逻辑右移还是算术右移,取决于编译器,一般情况,绝大多数编译器采用算术右移。这里以算术右移为例讲解。

和左移操作类似:

 注意:对于移位运算符,不要移动负数位,这个是标准未定义的!!!!!

int  num  =  10 ;

num >>  -1 ;  //error


3. 位操作符

&  //按位与

|   //按位或

^  //按位异或 

注意:他们全是按二进制位来操作的,且操作数必须是整数!

按位与:只有对应的两个二进制位均为1时,结果位才为1 ,否则为0。

按位或:只要对应的二个二进制位有一个为1时,结果位就为1。

按位异或:当两对应的二进制位相异时,结果为1。


4. 赋值操作符

=       复合赋值符:+=   -=   *=   /=   %=   >>=   <<=   &=   |=   ^=  

 赋值操作符这里大家应该都了解,我在就说明一个内容:


5. 单目操作符 

!               逻辑反操作
-               负值
+              正值
&              取地址
sizeof       操作数的类型长度(以字节为单位)
~              对一个数的二进制按位取反
--              前置、后置--
++            前置、后置++
*               间接访问操作符(解引用操作符)
(类型)       强制类型转换

!:逻辑反操作

 

&:取地址

* :间接访问操作符(解引用操作符)

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

~ :对一个数的二进制按位取反

--  :前置、后置--

++:前置、后置++

 (类型) :强制类型转换


6. 关系操作

>
>=
<
<=
!=       用于测试“不相等”
==      用于测试“相等”

这个可以用数学来理解,意思大致都是一样的。

唯独注意:==不能比较两个字符串的内容,它比较的是两个字符串的首字符的地址。其次,==和=书写时一定要注意,两者的意思天差地别。


7. 逻辑操作符

&&       逻辑与(并且)两个都为真就是真
 ||         逻辑或(或者)只要有一个为真就是真
只关心真假与二进制无关


8. 条件操作符 (三目操作符)

exp1 ? exp2 : exp3


9. 逗号表达式

exp1, exp2 ,exp3,......expn
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

10. 下标引用、函数调用和结构成员 

1. [ ] 下标引用操作符
2. ( ) 函数调用操作符
3. 访问一个结构的成员

10.1 [ ] 下标引用操作符

int main()
{
	int arr[10];
	arr[4] = 5;
	//[]下标引用操作符
	//操作数 arr和4 
}

10.2 ( ) 函数调用操作符

void add(int x, int y)
{

}

int main()
{
	add2();
    //操作数:add2
	add(5, 10);//()函数调用操作符 
	//操作数:add,5,10
}

10.3 访问一个结构的成员

.    结构体.成员名
->  结构体指针->成员名  

 


11. 表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

11.1隐式类型转换

C 的整型算术运算总是至少以默认整型类型(一般为int)的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升
整型提升的意义
  表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
一般就是int的字节长度,同时也是CPU的通用寄存器的长度。 因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。  
#include<stdio.h>

int main()
{
	char a = 5; //截断  因为char是一个字节也就是8个bit位 所以发生截断
	char b = 126;
	char c = a + b;
	//000000000000000000000000 00000101 a的补码
	//截断后 a- 00000101
	//000000000000000000000000 01111110 b的补码
	//截断后 b- 01111110
	//整型提升
	//00000000000000000000000000000101 -a
	//00000000000000000000000001111110 -b
	//00000000000000000000000010000011
	//10000011 -c
	printf("%d\n", c);
	// %d 十进制的方式打印有符号整数
	//11111111111111111111111110000011 补码
	//11111111111111111111111110000010 反码
	//10000000000000000000000001111101 原码
	return 0;
}
int main()
{
 char c = 1;
 printf("%u\n", sizeof(c)); // sizeof(c) ,是1个字节,因为不参与运算
 printf("%u\n", sizeof(+c));
//c只要参与表达式运算,就会发生整形提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字节
 printf("%u\n", sizeof(-c));
//表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof(c) ,就是1个字节
 return 0; }

11.2 算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行。
long double
double
float
unsigned long int
long int
unsigned int
int                           (向上转换)⬆

12. 操作符的属性

复杂表达式的求值有三个影响的因素:
  1. 操作符的优先级
  2. 操作符的结合性
  3. 是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们的优先级,如果两者的优先级相同,取决于他们的结合性。
例如:a + b * c      肯定是先计算* 再计算 +

 


网站公告

今日签到

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