C语言学习记录230625

        hello喔!~几天不见甚是想念,虽然昨天匆忙把自己的扫雷程序源代码发上来凑活了一下,但正儿八经的学习总结已经有好几天没发了,总而言之也是各种各样的原因吧。而且今天辅导班的老师还来问我对JAVASE有没有什么疑问,这就很尴尬,我还在学C,虽然老师建议我跳过C,但是我也问了一下,他们说先C语言学习过后,会对后续Java的学习更有好处,我本着夯实基础的原则,这才从头再过一次,今天老师来一问。顿时把我的紧迫感又拉了起来,还是得抓紧,暂定到下个月中旬结束C语言的初阶和进阶课程,开始入门javase。话说回来虽然时间紧,但是基础还是要老老实实地打,基础扎实才能万丈高楼平地起。今天主要是细讲了各种运算符,特别是对二进制数的一些运算符,我此前都没学习过,很庆幸这次能补上。

        (一)移位操作符

                由于算术运算符很简单,此前也说过,这里也是直接跳过吧,但是大概说一下算术运算符就是+、-、*、/、%。直接将对我来说比较有收获的运算符,由于《C方法》一书对应章节我还没看到,我也不知道有没有其他的称呼,我这里就按课程所给的名称称呼。

                移位操作符主要用于对二进制数的移位,这个移位指的是直接对整个二进制数移位。移位操作符包含两个双目操作符,一个朝左移动,一个朝右移动,符号为“<<”“>>”,很生动形象。另外移位操作符只能用于整型,浮点类型是不支持的。

                这个移位刚刚也说了,是对整个二进制数移位,那么整个移位是什么意思呢?虽然很抽象,但整个移位就是整个移位(笑),这边给出一个例子:

                假设有两个8位二进制有符号整数,十进制数分别为5和-5,我们还需要清楚一点,那就是在计算机中,这个十进制整数的二进制是以补码形式存在的,那么他们的原码、反码和补码如下:

十进制:5                                十进制:-5
二进制原码:00000101                     二进制原码:10000101
二进制反码:00000101                     二进制反码:11111010
二进制补码:00000101                     二进制补码:11111011

                可以看到正数的原码、补码、反码是一致的,而负数则相对复杂不少,负数的反码是将其除符号位以外的所有二进制位取反(0变1,1变0),补码则是在这个基础上再加1。

                知道上面的原码、反码、补码以后,我们就可以讨论移位运算符了,假设我们对这个5和-5运用左移运算符,移动一个二进制位,则变化后的补码、反码、原码及最终十进制数如下:

5<<1                                    -5<<1
二进制补码:00001010                     二进制补码:11110110
二进制反码:00001010                     二进制反码:11110101
二进制原码:00001010                     二进制原码:10001010
十进制:10                               十进制:-10

                因为正数简单,我们也从正数先说,对比上下两个代码图,可以看到正数就是直接整个二进制数左边移动一个二进制位,左边多出来的抛弃掉,而右边移动新增的位置用0填充,最终结果就是5变成了10,所以不难想象如果是移动2个二进制位,那就是5变成20。负数则复杂很多,首先负数的补码要先跟正数一样左移,也是左边超出范围的二进制位扔掉,右边新增的位置用0填充,然后补码减-1变成反码,再根据反码的规则,符号位不变,其他位取反,得到移位后的十进制数,-5变成了-10,所以自然也不能想象如果同样左移2个二进制位,一样会变成-20。

                右移操作符跟左移操作符原理一致,超出的位数舍弃,新多出来的空位用0填充。

                到这里,我们可能就会思考这东西到底有什么用?实际上这个操作符在很多场景会有所应用,在后面讲了对二进制数操作的其他操作符以后,我再进行总结。

        (二)位操作符

                位操作符跟逻辑运算符有一定相似,位运算符分为位与、位或、位异或,与跟或跟逻辑的与或很像,位运算符也是双目运算符,按位与操作符(&)对两个二进制数进行运算时,会对两个二进制数对应的二进制位逐位运算,规则是当两个二进制数位都为1时,则为1,若有一个为0,则都是0。下面给个例子:

十进制:  5                11
二进制:  00000101         00001011
5&10结果:00000001

                按位或操作符(|)对两个二进制数进行运算时,同样是逐位运算,当两个二进制位任意一个为1时,则均为1,只有两个都为0时,才会0,下面给出例子:

十进制:  5                11
二进制:  00000101         00001011
5|10结果:00001111

                按位异或操作符则麻烦一些,运算方式跟前面一样,但是规则略有不同,规则是只有当两个二进制位不同时才为1,相同则为0,例子如下:

十进制:  5                11
二进制:  00000101         00001011
5|10结果:00001110

                好了,包含移位操作符,和这里的位操作符,就是今天学到的所有对二进制位运算的操作符了,我很喜欢今天老师说的一句话,他说“我们通过这些运算符,能直接精确到对某个数的二进制里的某一位进行操作,这难道不是一件很棒的事情吗?”

                结合一些练习,确实有不少规律,比如当需要求一个数的二进制位里有几个1时,就能利用这里的运算符很方便的求解出来,大致有三种方式,第一种是传统的利用模拟除法的方法,直接依次将二进制位反向计算出来,定义一个计数器,当出现1时进行一次计数,这个方法,当数是正数时,是没问题的,但是当数是负数时,就会出问题,所以需要想想别的方法。

                第二种方法是利用移位操作符以及按位与操作符,原理就是首先利用按位与操作符将要求1位数的数与1的二进制按位与,运算的结果是,当这个数的最右边一位是1时,结果是1,为0,则结果为0,所以为1时,我们就利用计数器进行计数。进行上述操作以后我们再利用右移操作符将这个数最右侧的数抛弃掉,以便我们进行下一次按位与。下面可以给出例子:

十进制:    5                      十进制:    6        
二进制:    00000101               二进制:    00000110
1的二进制: 00000001               1的二进制:  00000001
1&5     :  00000001               1&6     :   00000000 

                 利用上面这种原理,就可以无视正负数,求出二进制位里1的数量。

                第三种方法我也只是知道能那么做,具体为什么,我也不知道,可以当成一种技巧看,假设要求解数量的数为n,那么当n^(n-1)时,就能删除掉这个数最右边的一个为1的二进制位,我们对这个数内部二进制位里的1不断删除,直接这个数里的1被删完,他的值变为0位置,我们需要用计数器对这个删除的次数进行统计。

                最后再补充一个单目运算符“~”,可以对一个数的二进制位全部取反。

        (三)杂七杂八的其他运算符

                其实还有一个赋值操作符,赋值操作符相对简单,这里就就不展开谈了,主要就是简单赋值运算符和复合赋值运算符。

                其实其他单目运算符也没啥好讲的,这里sizeof可以注意一下,sizeof通常的形式是sizeof(),这里的()其实可以不用加,这里就是他跟函数最大的外在特征区别。

                此外取地址运算符&对静态数组数组名直接取地址时,取的是整个数组的地址。

                关系运算符、逻辑运算符、条件操作符、逗号运算符其实之前都讲过,这里一概跳过。

                今天下标引用运算符倒是让我知道了个有趣的事情,假设我们有一个数组word,他有20个元素,当我们对第20个元素进行访问时,可以有下面这么三种写法:

                word[19]、(*word)[19]、*(word+19)、*(19+word)

                看最后一个*(19+word),我们知道有加法交换律,并且[]我们知道了是一个双目的运算符,那么word[19]是否能写成19[word],并且两者等价呢?实际上这两者也是等价的,而且在编译过程中,他们实际表达的都是*(word+19)。

        (四)整型提升

                其实这块我更建议看下《C方法》一书,其中对这块有十分详细的解释,说的通俗点就是计算机在计算过程中需要保证计算的数类型一致,以及需要尽量保证让计算结果在对应类型的可容纳范围之内,为此有着一套详细的转换规则。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值