前言:相信大家通过之前的学习,已经了解了一些操作符(算术,逻辑,条件,赋值等),然而,一些操作符是跟二进制结合的,接下来让我们一起学习吧!
(大家可以根据目录学习哦 !)
1.操作符的分类
算术操作符:+ 、- 、* 、/ 、%
移位操作符: << >>位操作符: & | ^ `赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^=单目操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型)关系操作符: > 、>= 、< 、<= 、 == 、 !=逻辑操作符: && 、||条件操作符: ? :逗号表达式: ,下标引用: []函数调用: ()结构成员访问: . 、 ->
2.二进制和进制转换
相信大家听说过二进制、八进制、十六进制,那他们到底是什么意思呢?
其实呀,它们只是一个数不同的表达形式而已
在我们不熟悉它们的时候,我们可以用程序员计算器进行计算和换算
程序员计算器的使用
点击电脑开始按键
左上角切换成程序员模式
字母的意思
我们可以算出各种数的不同进制的表达
15的2进制:111115的8进制:1715的10进制:1515的16进制: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 doubledoublefloatunsigned long intlong intunsigned intint如果某个操作数的类型在上面这个列表中排名靠后,那么首先要转换为另外⼀个操作数的类型后执行运算。
表达式的注意事项
我们在实际操作中尽量避免使用以下用法,因为这些有的会使编译器报错,也会根据不同编译器得出不同结果,而且其本身就有实际问题