详解各类操作符

目录

前言

1 算术操作符

2 移位操作符

 3 位操作符

4 赋值操作符

5 单目操作符

5.1  ! 逻辑反操作

 5.2 sizeof  和数组

6 关系操作符

7 逻辑操作符

8 条件操作符

9 逗号表达式

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

10.1[ ] 下标引用操作符

 10.2 ) 函数调用操作符

10.3 访问一个结构的成员

 11 表达式求值

11.1整形提升

11.2优先级和结合性 

 总结


前言

大家好啊!我是^O^玩转编程,这期博客我将为大家详细讲解各类操作符的用途和功能。

1 算术操作符

+    –   *   /   %

+,-*操作数我就不多说了,这里我们重点来 / %

/操作数

作用:就是求商

注意点:

1 二边的操作数都是整形,商的结果就为整数

2 二边的操作数有一个是浮点型结果就为小数

%操作数

作用:求余数

注意点:. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。

2 移位操作符

<< 左移操作符

>> 右移操作符

注意:移位操作符移的是二进制位,且操作数只能是整数

<< 左移操作符

规则:左边抛弃、右边补0

代码举例:

#include<stdio.h>int main)
{int a = -5;
//正数的原码,反码和补码都相同
//这是负数的规则:
//10000000000000000000000000000101原码
//11111111111111111111111111111010反码(原码的符号位不变,其他位按位取反)
//11111111111111111111111111111011补码(反码+1就是补码)int b = a << 1;
//11111111111111111111111111110110补码
//11111111111111111111111111110101反码
//10000000000000000000000000001010原码printf"a = %d\n", a);printf"b = %d\n", b);return 0;
}

当a<<1时

当a<<2时

当a<<3 时

 总结:

1 操作数被移位操作符操作后其值仍然不变

2 计算机存储的都是补码,而打印出来的是原码所对应的值

3 b=a<<n时,b的值位a*2^n,也就是说当我们左移1位时相当与乘了个2倍

>> 右移操作符

移位规则: 首先右移运算分两种:

1. 逻辑移位 左边用0填充,右边丢弃

2. 算术移位 左边用原该值的符号位填充,右边丢弃

代码举例:

#define  _CRT_SECURE_NO_WARNINGS#include<stdio.h>int main)
{int a = -64;int b = a >> 1;printf"a = %d\n", a);printf"b = %d\n", b);return 0;
}

当a>>1时

 当a>>2时

 当a>>3时

  总结:

1右移操作和左移操作是本质都是对补码的二进制位进行操作

2 b=a>>n时,b的值位a/2^n,也就是说当我们左移1位时相当与除了个2倍

注意:

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

 3 位操作符

& //按位与

| //按位或

^ //按位异或

注:他们的操作数必须是整数。

 我们这些位操作符都是针对操作数的补码进行操作的

&操作符

作用:对于二进制数,都为0才为0都为1才为1

代码举例:

#include<stdio.h>int main)
{int a = 5;
//00000000000000000000000000000101  5的补码int b = -3;
//10000000000000000000000000000011  3的原码
//11111111111111111111111111111100  3的反码
//11111111111111111111111111111101  3的补码int c = a & b;
//00000000000000000000000000000101  5的补码
//11111111111111111111111111111101  3的补码
// &的作用是二进制数,都为0才为0都为1才为1
//00000000000000000000000000000101  c的补码printf"a = %d\n", a);printf"b = %d\n", b);printf"c = %d\n", c);return 0;
}

 |按位或

作用:二进制位中有一个为1就为1,
^按位异或

作用:二进制位中相异置1,相同为置0

大家知道这些操作符的作用了,我们来做到题目来实战一下吧。

题目1:不能创建临时变量(第三个变量),实现两个数的交换

 代码实现:

#include<stdio.h>
int main)
{int a = 2;//0010int b = 3;//0011printf"交换前a = %d,b = %d \n", a, b);a = a ^ b;//a的值0001b = a ^ b;//b的值00102)a = a ^ b;//a的值00113)printf"交换后a = %d,b = %d\n", a, b);return 0;
}

题目2:编写代码实现:求一个整数存储在内存中的二进制中1的个数。

 代码实现

//num&1便会找到二进制最低位是否为1
#include<stdio.h>
int main)
{int num = -1;int i = 0;int count = 0;//计数for i = 0;i < 32;i++){if num & 1 << i)){count++;}}printf"二进制数中1的个数:count = %d\n", count);return 0;
}

总结:

我们要想看二进制中的最低位是1还0,我们就可以通过&1来实现。

4 赋值操作符

=

 这个操作符是用来赋值的,我们要于‘==’区分,这个是用来表示相等的,大家是否在编程的时候会弄错呢?下面教大家一种写法可以在很大程度上避免这种错误。

#define  _CRT_SECURE_NO_WARNINGS#include<stdio.h>int main)
{int a = 1;if 1 == a){printf"可以避免错误\n");}
}

要是我们写成1=a,就会报下面的错误,这样我们就能够及时的改正自己的错误,是不是很好呢。

 复合赋值符

+= 

-= 

*= 

/=

%=

>>=

<<=

&=

|=

^=

 这些都是=操作符的复合形式,举个例子。

a+= 10;就相当于a=a+10;

a-=10;就相当于a=a-10;

5 单目操作符

!           逻辑反操作

–           负值

+           正值

&           取地址

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

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

—          前置、后置–

++          前置、后置++

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

类型)       强制类型转换

单目操作符的操作对像是1个,下面我们来一一细说。

5.1  ! 逻辑反操作

就是让真变假假变真

代码举例:

#include<stdio.h>int main)
{int a = 0;int b = 1;int c = !a;int d = !b;printf"c = %d,d = %d\n", c, d);return 0;
}

 5.2 sizeof  和数组

sizeof是用来求操作数的类型长度(以字节为单位)

下面我们来看到这段代码

#include <stdio.h>
void test1int arr[])
{printf"%d\n", sizeofarr));//2)
}
void test2char ch[])
{printf"%d\n", sizeofch));//4)
}
int main)
{int arr[10] = { 0 };char ch[10] = { 0 };printf"%d\n", sizeofarr));//1)printf"%d\n", sizeofch));//3)test1arr);test2ch);return 0;
}

他们的结果分别是  40 10 4 4,为什么呢?

第一个我们求的是整的数组的大小,arr有10个元素,每个元素都是整形,所有数组的大小为40个字节。

第二个ch有10个元素,每给个元素为char 类型,所以ch数组大小为10字节

第三个和第四个传的是数组名(本质上都是首元素地址),那么对于test1和test2应该用指针来接收,所以在test1和test2其实求的是指针的大小,在32平台,指针的大小应该为4个字节。

6 关系操作符

>

>=

< <=

!=   用于测试“不相等”

==      用于测试“相等”

7 逻辑操作符

&&     逻辑与

||          逻辑或 

 用一道例题来说明逻辑操作符

#include <stdio.h>
int main)
{int i = 0, a = 0, b = 2, c = 3, d = 4;i = a++ && ++b && d++;//i = a++||++b||d++;printf"a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);return 0;
}

 为什么b= 2,c= 3,d =4呢?我们不是进行来对bcd进行了前置++或者后置++的操作吗?

这是因为对于&&来说只要他的左表达式为假了,后面就不在执行

而对于||来说只要左表达式为真,后面就不在执行了

8 条件操作符

xp1 ? exp2 : exp3  

这个意思就是如果xp1为真,就执行exp2,否则就执行exp3。

9 逗号表达式

exp1, exp2, exp3,…….expN

逗号表达式,就是用逗号隔开的多个表达式。

逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果

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

10.1[ ] 下标引用操作符

操作数:一个数组名 + 一个索引值

 对于一个已经初始化的数组来说,arr[7]和7[arr]及*(arr+7)都是等价的。

#include<stdio.h>int main)
{int arr[10] = { 0 };arr[7] = 5;printf"arr[7] = %d\n", arr[7]);7[arr] = 6;printf"arr[7] = %d\n", arr[7]);*arr + 7) = 7;printf"arr[7] = %d\n", arr[7]);return 0;
}

 10.2 ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数

10.3 访问一个结构的成员

. 结构体.成员名

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

 11 表达式求值

对于一给表达式我们一般要考虑它的计算操作符的优先级结合性,当表达式进行求值的时候还可能会发生整形提升。

11.1整形提升

什么是整形提升呢?就是在计算的计算的过程中都是默认以整形的方式进行计算的,当我是char类型参与计算时候就要发生整形提升。

整形提升规则:

负数的整形提升

char c1 = -1;

变量c1的二进制位补码)中只有8个比特位: 1111111

因为 char 为有符号的 char

所以整形提升的时候,高位补充符号位,即为1

提升之后的结果是: 11111111111111111111111111111111

正数的整形提升

char c2 = 1;

变量c2的二进制位补码)中只有8个比特位:

00000001

因为 char 为有符号的 char 所以整形提升的时候,高位补充符号位,即为0

提升之后的结果是: 00000000000000000000000000000001

无符号整形提升,高位补0

11.2优先级和结合性 

对于应该复杂表达式的求值有三个影响的因素。

1. 操作符的优先级

2. 操作符的结合性

3. 是否控制求值顺序。

两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

那么我们知道了解复杂表达式的3个元素,那么表达式求数的结果一定说唯一的吗?

下面我们来看到问题表达式

int c = 1;

int b = c+ –c;

请问b中的值是什么?

 b=1?b=0?为什么二个结果呢?

对–操作符的优先级是比+高的,但是并没有规定系统是怎么给C准备空间的,如果开始为就表达中的c开辟了空间,那么结果就为1,如果是在–c之后在开辟空间的,那么结果就为0。

 这些问题表达式我们要谨防在我们的代码中出现。

 总结

对于这些操作符,不是看完这篇博客将能掌握的,大家还是要在写代码多练习。

大家喜欢的话,来个三连支持博主吧!​​​​​​  

 

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注