七. C语言操作符与二进制

       前言:相信大家通过之前的学习,已经了解了一些操作符(算术,逻辑,条件,赋值等),然而,一些操作符是跟二进制结合的,接下来让我们一起学习吧!

(大家可以根据目录学习哦 !)

1.操作符的分类

 算术操作符:+ - * / %

 移位操作符: << >>
 位操作符: & | ^ `
 赋值操作符: = += -= *= /= %= <<= >>= &= |= ^=
 单目操作符: !、++--&*+-~ sizeof(类型)
 关系操作符: > >= < <= == !=
 逻辑操作符: && ||
 条件操作符: ? :
 逗号表达式: ,
 下标引用: []
 函数调用: ()
结构成员访问: . ->

2.二进制和进制转换

相信大家听说过二进制、八进制、十六进制,那他们到底是什么意思呢?

其实呀,它们只是一个数不同的表达形式而已

在我们不熟悉它们的时候,我们可以用程序员计算器进行计算和换算

程序员计算器的使用

点击电脑开始按键

左上角切换成程序员模式

字母的意思

我们可以算出各种数的不同进制的表达

152进制:1111
158进制:17
1510进制:15
1516进制:F

二进制

我们都知道

10进制中满10进1,且10进制的数字每位都是由0~9的数字组成

那么对于二进制来说,道理是一样的

2进制中满2进1,且2进制的数字每位都是由0~1的数字组成

进制转换

十进制每位数的权重是(从右向左): 10^0  ,10^1  ,10^2   ....

二进制每位数的权重是(从右向左):  2^0  ,2^1  ,2^2   ....

(其它进制我们可以类比,在这里不多说啦)

那么它们之间该如何转换呢?

接下来展示一张图,我们要熟悉这张图,并掌握它们之间的规律

大家仔细探索之间的规律噢!

 2进制转10进制

 10进制转2进制

快捷方法:
        假设我需要求133的二进制
        我们可以这样
对于初学者的我们可以多算算

2进制转8进制

我们要知道,8进制每位数都是0~7的,如果把0~7写成2进制,我们会发现(可以自己探索为什么哟),它们最多占用三个2进制位,这就有利于我们进行它们之间的转换

例如:

  我们把2进制的 :11010111  转换成8进制    

(不熟悉的可以对照上面的表哟)

 2进制转16进制

16进制每位数字是0~9,a~f (到9后从a继续,相当于a是第11位数),同样的,我们会发现,它们最多占用2进制的四位,按照转8进制的方法,我们再拿2进制的11010111举例:

进制转换这一块不算难,还不懂的小伙伴可以多加练习哦

3.原码、反码、补码

  原码、反码、补码注意事项

整数的2进制表示方法有三种,原码、反码、补码

有符号整数的这三种表示方法均有符号位和数值位两部分,在这些数的2进制序列中,最高位(最左边那个数字)当作符号位,剩下的数字都是数值位.

符号位用0表示“正”,用1表示“负”

注意:

在C语言中,整数通常泛指所有整数类型包括有符号整数和无符号整数

举例说明

int 类型中,假如存放数字 10,那么它在内存中占4个字节==32个比特位,也就是说

10 的 2进制是 1010,在内存中它需要32-4位来填充,即在内存中 10 表示为

     

三码转换

正整数的原、反、补码都相同

负数三种表示方法各不相同

原码:直接将数值按照正负数形式翻译成2进制

反码: 原码符号位不变,其它位依次取反(0→1,1→0)

补码:反码+1

如图示:

例如-10:

三码的意义

对于整型来说,数据存放在内存中的是补码

因为:

在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀ 处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算 过程是相同的,不需要额外的硬件电路。
它们在内存中存放的都是补码,计算的也都是补码

4.移位操作符

这一部分比较难理解,也比较重要,希望大家认真学习(下面展示的二进制都是补码)

<< 左移操作符

>> 右移操作符

注意:移位操作符的操作数只能是整数

左移操作符

   移动规则:左边抛弃、右边补零                                                                                                 

   我们同样拿十进制的 10 举例

右移操作符

移位规则:分两种(根据编译器不同)(大部分编译器是算数右移)

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

2.算数右移:左边用该值的符号位填充,右边丢弃(VS)

我们重点说一下算数右移算术右移弄明白了,逻辑右移也就弄明白啦

我们首先拿10二进制举例(算数右移)

(正数两个位移结果其实是一样的)

我们再拿 -10 举例

这样我们就比较清楚的了解了它们怎样操作的

代码实现的注意事项

假如我们对 m 进行位移时,它最后输出的值还是10,我们可以把m>>的值赋给 n,这样n就是 m>> 的值了,这点我们要注意

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

5. 位操作符 :&、| 、^ 、~

  我们之前在for 循环章节中学过 && ——并且 (逻辑与) 和 || ——或者(逻辑或),它们属于逻辑操作符,而 &、| 、^ 、~,位操作符,分别是

&     ——按位与

|      ——按位或

^      ——按位异或

~     ——按位取反

注意:它们操作的都是整数

上面是它们的运算规则(找了一张大家比较能看懂的图)

这些需要我们好好记住哦

(作者在不断学习,下面红色部分将不断更新)

1.

a^a=0

0^a=a

例如:

1^2^3^2^1=3

2.

& 操作符有这样一个作用

当某个数进行&1计算时,我们会的到这个数二进制的最后一位(0或1)

通过这样的计算我们能对某个数的二进制数中0和1的各种统计

6.单目操作符

这些我相信大家已经烂熟于心了吧,这里 就不罗列它们的作用了,如果想要了解的请看前面几章的内容.

!、++--&*+-~ sizeof(类型)

7.逗号表达式

 这一部分是值得说一下的

逗号表达式:exp1, exp2, exp3, …expN
重点就是:逗号表达式从左向右依次执行, 整个表达式的结果是最后一个表达式的结果
int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);
	//请问c是多少?
	return 0;
}

请问c是多少?

这道题大家可以思考一下,这里我不多说了(初学者错误百出,一定要遵循其语法规则)

8.下标访问 [ ]

我们在之前学习数组和函数的时候已经见过这东西了,这里我再次说明一下其语法规则

[]  下标引用操作符

规则:  一个数组名+一个下标

int arr[10]——创建数组

arr[9]=10——使用下标引用操作符

[   ]两个操作数是 arr 和 9

9.函数调用 ( )

我们之前在 扫雷那里大量使用了函数以及函数调用,具体是什么我相信大家在学习函数那一章已经非常明白了,在这里我就简单举个例

10.结构成员访问操作符

这一部分之前没有接触过,所以我来详细讲一下,这里也比较重要,这与后面我们要学的C语言指针有着重要联系,接下来让我们一起学习吧!

 结构体

我们仔细回想一下之前的学习历程,我们学了许多类型:int 、char、 float  等,随着对他们的深入学习我们会发现,这些仅仅是最基础的一些类型信息,而当我们要描述更复杂的信息,如:一个人的姓名,身高,体重,甚至家庭地址等,我们需要更为细腻的操作来操作他们,对此,C语言增加了结构体这种自定义的数据类型

结构:它是一些的集合,就相当于我们中学数学学的集合,只是在这个集合中我们可以有不同类型的元素,例如 : [ 身高,名字,体重  ]

结构的声明

语法如下(学多了会发现,有些东西的语法本质上是差不多的,只是个别地方有差别)

比如我想要统计二十名学生的信息

结构体变量的定义和初始化

我们看到上面初始化时需要按照 声明的顺序 去使用

那么我们不想按照顺序可以吗?答案是:当然可以

具体操作看下图

结构体成员的直接访问

直接访问是通过操作符   “   .   ”进行访问的

具体上图即可明白

直接访问:结构体变量.成员名

间接访问:结构体指针->成员名

(结构体成员间接访问涉及到指针,等我们学到指针那一章节细讲哦!)

11.操作符的属性:优先级、结合性

操作符的这两个属性决定了表达式求值的顺序

优先级

就像我们当初学习数学中先乘除后加减一样,在C语言中,如果一个表达式包含多个运算符,哪个运算符优先级高哪个运算符先执行

例如: 在C语言中   3 + 4 * 5,先计算  4*5 ,再计算 3+20

结合性

如果两个运算符优先级相同,就要看结合性了

大部分运算符是左结合(从左到右执行)

少数运算符是右结合(从右到左执行 ),比如赋值运算符(=)

下列表是优先级和结合性

具体内容可以参考:https://zh.cppreference.com/w/c/language/operator_precedence

12. 表达式求值

整型提升

C语⾔中整型算术运算总是⾄少以缺省整型类型的精度来进⾏的。 为了获得这个精度,表达式中的字符和短整型操作数在使⽤之前被转换为普通整型,这种转换称为整 型提升。
整型提升的意义:
表达式的整型运算要在CPU的相应运算器件内执⾏,CPU内整型运算器(ALU)的操作数的字节⻓度⼀
般就是int的字节⻓度,同时也是CPU的通⽤寄存器的⻓度。
因此,即使两个char类型的相加,在CPU执⾏时实际上也要先转换为CPU内整型操作数的标准⻓
度。
通⽤CPU(general-purpose CPU)是难以直接实现两个8⽐特字节直接相加运算(虽然机器指令中
可能有这种字节相加指令)。所以,表达式中各种⻓度可能⼩于int⻓度的整型值,都必须先转换为
int或unsigned int,然后才能送⼊CPU去执⾏运算
(源自网络)
整型提升规则:
1. 有符号整数提升是按照变量的数据类型的符号位来提升的
2.无符号整数提升,高位补0
负数整型提升
char c1 = -1;
变量 c1⼆进制位(补码)中只有8个比特位:
1111111
因为 char 为有符号的 char
所以 整形提升的时候, 高位补充符号位,即为 1
提升之后的结果是:
111111111111111111111111111111111
正数整型提升
char c2 = 1;
变量 c2⼆进制位(补码)中只有8个比特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候, 高位补充符号位,即为 0
提升之后的结果是:
00000000000000000000000000000001
无符号整形提升,高位补0

算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中⼀个操作数的转换为另⼀个操作数的类 型,否则操作就无法进行。下⾯的层次体系称为寻常算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名靠后,那么首先要转换为另外⼀个操作数的类型后执行运算

表达式的注意事项

我们在实际操作中尽量避免使用以下用法,因为这些有的会使编译器报错,也会根据不同编译器得出不同结果,而且其本身就有实际问题 

总结:操作符是我们写代码必不可少的东西,它们各个之间联系紧密,我们不仅要掌握如何使用,也要避免使用不恰当的方式操作,初学者不建议写出复杂的表达式。

作者留言:本人初学者,制作不易,如有错误,欢迎大家指出与修正
                     
                         制作时间:2023.12.13
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值