【五一创作】速通C语言第五站 一篇博客带你详解操作符

系列文章目录

速通C语言系列

 速通C语言第一站 一篇博客带你初识C语言        http://t.csdn.cn/K43IN

 速通C语言第二站 一篇博客带你搞定分支循环   http://t.csdn.cn/O9ISr

 速通C语言第三站  一篇博客带你搞定函数         http://t.csdn.cn/vkcsU

速通C语言第四站  一篇博客带你学会数组         http://t.csdn.cn/Ol3lz


五一快乐! 感谢佬们阅读支持!

我是一个特别固执的人,我从来不会因为到了五一就不卷,如果

你们也可以像我一样,那么我觉得这件事情……

文章目录

  • 系列文章目录
  • 前言
  • 补充
  • 一、各种操作符的介绍
  •        1 位操作符
  •              面试题
  •        2 对逻辑运算符的补充
  •             &&
  •             ||
  •        3 对单目运算符的补充
  •               sizeof
  • 二、表达式求值
    • 1.隐式类型的转换
    •       整形提升
    •      .算数转换
    • 2.操作符的属性
    • 3 问题表达式
  • 总结


前言

     在初始C语言中,我们介绍了一些操作符,这篇博客将带大家学习初始C语言中未做介绍的操作符或对已经介绍过的操作符进行一波补充。 下面,我们就开始吧!     


补充

   我们先来补充一些概念

在C/C++中,我们把int、 char、double等和所有指针等这些由C/C++所提供的类型叫做内置类型,而把那些结构体等由我们自己实现的类型叫做自定义类型。

由此,我们得知编译器“认识”内置类型,而“不认识”自定义类型

编译器知道如何对内置类型操作,而不知道如何对自定义类型操作

所以在C语言阶段,操作符只能对内置类型操作。


一、各种操作符的介绍

   1 位操作符&              |                 ^

按位与     按位或        按位异或

&

两个数对应的二进制位中

两个至少一个为0--------》0

两个都为1-----------------》1

给一波例子

#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	//& 按位与
	int c = a & b;
	printf("%d\n", c);
	return 0;
}

 在上面的规则下,我们得出结果

 即为1


 |

两个数对应的二进制位中

两个至少一个为1--------》1

两个都为0-----------------》0

给一波例子

int main()
{
	int a = 3;
	int b = 5;
	//| 按位或
	int c = a | b;
	printf("%d\n", c);
	return 0;
}

得出结果

即为7 


^

两个数对应的二进制位中

两个不同-----------------》1

两个相同-----------------》0

给一波例子

int main()
{
	int a = 3;
	int b = 5;
	//^按位异或
	int c = a ^ b;
	printf("%d\n", c);
	return 0;
}

得出结果

 即为6

 另外,有性质

a^a=0

0^a=a


面试题 

许多面试题都是以位操作符展开的,下面给出三个题玩一玩

例一:

交换a,b的值,但不能引入第三方变量。

不能引入第三方变量,就是限制我们使用之前的“给临时变量再交换"的方法。

这里给出两种方法

法一:

a=a+b;
b=a-b;
a=a-b;

这种方法很好理解,但是如果a,b过大,就会溢出(int有大小限制)。


法二:使用(按位异或)^

a=a^b;
b=b^a;
a=a^b;

这个方法有点难理解,我给大家画一波图

 (成功交换)而且也不会存在溢出的问题.


例二:

判断一个数的二进制位有几个1

这个题的方法有很多,此处我们用按位与的方法,更多牛逼的方法详见我这篇速通C语言支线第一站 基础刷题 http://t.csdn.cn/kbEBq

比如给个 int a=13

让他按位与1

如果最后一位是1,得到的就是1

然后再用移位操作符+循环让他左移。

上代码

int Set(int n)
{
	int i = 0;
	int count = 0;
	//由于一个数的二进制位有32位,所以循环32次
	for (i = 0; i < 32; i++)
	{
		//用>>右移二进制位
		if ((n >> i) & 1 == 1)
		{
			count++;
		}
		return count;
	}
}

例三:

改变一个数二进制的某一位

int a=13

还是画一波图

 

比如要改变这个位置

将其按位与

   (1<<4)

a=a|(1<<4);

如何再改回来?

在前面加上~(逻辑反)即可。

a=&~(1<<4);

 2 对逻辑运算符的补充

&&

先给一段程序,大家来看看a,b,c,d的值各为多少

int main()
{
	int i = 0;
	int a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
	printf("%d %d %d %d", a, b, c, d);
	return 0;
}

看似是 

a=1 b=3,c=3,d=5

但运行之后

 结果是 1 2 3 4 。为什么?


这里要介绍&&的一个性质了

在有很多&&的一个式子中,自左向右来看,如果出现了一个假,那后面的东西都将忽略,整个式子的值为假。

所以在这个题中,a是后置++,所以在使用时,a=0,0为假,所以整个式子的值已经为假了,后面的++b,d++就被忽略了,所以b=2,d=4.


同理可得 || 的类似性质,

在有很多 || 的一个式子中,自左向右来看,如果出现了一个真,那后面的东西都将忽略,整个式子的值为真。

我们沿用上面的例子做修改

i = a++ || ++b || d++;

a为假,b为真,所以后面的d++就不算了,所以结果为

1 3 3 4


总结:&&一遇到假,后面就不算了

            ||  一遇到真,后面就不算了


 3 对单目运算符的补充 

     sizeof

  使用方式

我们直接上例子理解 

例:

int a = 10;
	//正常
	printf("%d\n", sizeof(a));
	//由于sizeof不是函数,所以可以不加括号
	printf("%d\n", sizeof a);
	//直接算类型
	printf("%d\n", sizeof (int));

三种方式均可得出答案


sizeof内部不计算

例:

int main()
{
	int a = 10;
	short s = 5;
	printf("%d\n", sizeof(s = a + 3));
	return 0;
}

如果这波sizeof计算了,s就会整形提升为int,结果就会变成4

但是sizeof内部不计算,所以结果为s的大小,即为short的大小,即为

2


二、表达式求值

1.隐式类型的转换

在编译时由编译程序按照一定规则自动完成,而不需人为干预。因此,在表达式中如果有不同类型的数据参与同一运算时,编译器就在编译时自动按照规定的规则将其转换为相同的数据类型。通俗来讲,就是偷偷发生的转换

另外,后期我们学习C++时,可以用一个关键字来阻止隐式类型的转换。 

      整形提升

C的整形算术运算总是以缺省型类型的精度来进行的

为了获得精度,表达式的字符(char,1bit)短整型(short,2bit)在使用前

被被转换为普通整形,这种转换成为整形提升。 

简单来看,只要不超过4bit的,就要发生整形转换,因为CPU内的整形运算器,一般为4bit的int类型。

另外,整形提升的规则是 按变量的数据结构的符号位来提升的。

例:

int main()
{
	char a = 3;
	char b = 127;
	char c = a + b;
	printf("%d\n", c);
	return 0;

}

在这一个式子中,a,b为char类型,均未达到一个int的大小,所以发生整形提升

 由于a,b符号位为零,所以提升时高位补零。

然后提升后的a,b做计算,结果为

但是这个结果要保存到c中,c是个char类型,只能保存8个比特位,那怎么办?

只能是将原结果截断为8个比特位

而打印出来,则又需要整形提升

高位为1,所以是一个负数,内存中存的是补码,而打印出来的是原码

我们需要做原码、反码、补码的转换

所以最终结果为-126。


 这里我们对char 、unsigned char做一个补充

 char的最高位是符号位,其大小范围为-128~127

 而unsigned char最高位不是符号位,其大小范围为0~255

 

 这两张图非常重要,希望大家牢记


 .算数转换

如果某个操作符的各个操作数属于不同的类型,那么除非一个操作数转换为另一个操作数的类型,否则操作就无法进行。

我们用图的方式来给出算数转换的规则

 比如int + long int,需把int 转为 long int 。


2.操作符的属性 

复杂表达式求值有三个影响因素 

1 操作符的优先级        两个相邻的操作符先执行哪个?

2 操作符的结合性        左结合(从左向右执行) 右结合(从右向左执行)

3 是否控制求值顺序(一般没有)

     二般:如 &&,左边为假,右边就不用算了,因为整个表达式已经是假的了

具体每个操作符的优先级、结合性,这里我给到一张表,我们可以直接查 

举一波例子

   a+b*7

* 优先级大于 + 。所以先乘再加.    

//优先级决定了运算顺序

int c=a+b+7

优先级相同,加号的结合性事左结合,所以先a+b,再加7

//结合性决定运算顺序


3 问题表达式

即使我们学习了以上知识,仍有可能算不出一些表达式的值

比如

a*b+c*d+e*f

如果按优先级来看,就是先乘,后加,顺序即为


但如果,从结合性来考虑

 前两个式子算出结果后先相加,再算第三个式子,再加起来。顺序就为

再给一个例子

c+ --c

优先级上,-- 大于 + 

我们设C等于3

第一种

3+(3-1)=5


第二种

先让--c算,3-1,所以原式为

(3-1)+(3-1)=4


所以我们无法确定唯一的计算路径 

同样的代码,不同的平台下都可能会不同


总结

   做总结,今天给大家补充了几个操作符的点以及表达式计算的规则,相较于前几篇博客,难度和重要性都有下降,大家只要理解并记住即可。水平有限,还请各位大佬指正。如果觉得对你有帮助的话,还请三连关注一波。希望大家都能拿到心仪的offer哦。

 每日gitee侠:今天你交gitee了嘛

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值