开篇请各位猿友允许LZ啰嗦几句,最近一直在写计算机系统原理这系列文章,也已经下定决心要把这本书的内容写完。主要目的其实是为了巩固LZ的理解,另外也想把这些内容分享给猿友们,毕竟LZ觉得这些内容对程序猿的实力还是有着很大的潜在提高的。

只是这种原理性的文章写起来相对复杂与繁琐,较对起来也比较困难,因为文章里充斥着各种各样的数学符号,不过相对于这样的写作难度来说,其受欢迎程度,却远远比不上一些难度较低的杂文。这一点从LZ的博客就能很明显的看出,LZ博客排名前几的文章,几乎全部都是LZ写的一些杂谈,比如经历、建议、感悟等等这一类的。

不过LZ也很理解这种现象,毕竟杂文看起来不怎么需要动脑子,内容相对来说也比较有趣,而且说不定偶尔也能有意外的大收获,受欢迎自是无可厚非的。不过对于计算机系统原理这种文章来说,倘若各位猿友能够坚持看下去的话,应该是会有不少的收获的。

此外LZ也希望各位猿友在观看之余,也不妨给予LZ一些鼓励和支持,这样不仅LZ的动力会大大增加,也会由于猿友们的鼓励而产生更大的责任感,从而更加费心的将内容更简单的解释清楚。

废话就到此结束吧,再写下去的话估计有猿友要忍不住吐槽LZ废话连篇了。就此打住,其实说了这么多,LZ就是想说五个字,“点个推荐吧。”

引言

在上一章中,我们着重介绍了整数的表示方式,也就是无符号编码和补码编码。本次我们来看一下二进制整数的扩展与截断,这部分内容是与C语言挂钩介绍的。因此我们首先来简单的看一下C语言的有符号数和无符号数。

C语言中的有符号数和无符号数

有符号数和无符号数的本质区别其实就是采用的编码不同,前者采用补码编码,后者采用无符号编码。

在C语言中,有符号数和无符号数是可以隐式转换的,不需要手动实施强制类型转换。不过也正是因为如此,可能你不小心将一个无符号数赋给了有符号数,就会造成出乎意料的结果,就像下面这样。

#include <stdio.h>

int main(){
    ;
    unsigned short u = i;
    printf("%d %d\n",i,u);
}

结果如下。

一个不小心,一个负数就变成正数了,再看下面这个程序,它展示了在进行关系运算时,由于有符号数和无符号数的隐式转换所导致的违背常规的结果。

#include <stdio.h>

int main(){
    printf( < 0U);
    printf( < 12345U);
}

结果如下。

可以看到,两个结果都为0,也就是false,这与我们直观的理解是违背的,原因就是因为在比较的过程中,有符号数被隐式的转换成了无符号数进行比较。

扩展

当我们将一个短整型的变量转换为整型变量时,就涉及到了位的扩展,此时由两个字节扩充为四个字节。

在进行位的扩展时,最容易想到的就是在高位全部补0,也就是将原来的二进制序列前面加入若干个0,也称为零扩展。还有一种方式比较特别,是符号扩展,也就是针对有符号数的方式,它是直接扩展符号位,也就是将二进制序列的前面加入若干个最高位。

对于零扩展来说,很明显扩展之后的值与原来的值是相等的,而对于符号扩展来说,则是一样,只不过没有零扩展来的直观。我们在计算补码时有一个比较简单的办法,就是符号位若为0,则与无符号是类似的。若符号位为1,也就是负数时,可以将其余位取反最终再加1即可。因此当我们对一个有符号的负数进行符号扩展时,前面加入若干个1,在取反之后都为0,因此依旧会保持原有的数值。

总之,在对位进行扩展时,是不会改变原有数值的。

在书中对于负数的符号扩展还给出了这一过程的证明,LZ这里就不多做叙述了,其实这个证明很简单,就是利用了补码编码的公式而已。需要多提一句的是,这里使用了归纳法证明,因此这里只是扩展了一位,具体过程如下。

截断

截断与扩展相反,它是将一个多位二进制序列截断至较少的位数,也就是与扩展是相反的过程。

根据我们的直观判断也不难发现,截断可能会导致数据的失真。对于无符号编码来说,截断后就是剩余位数的无符号编码数值。在书中给出了这一简单过程的证明,它主要是想表明截断前与截断后的数值的关系是取模所得到的。

对于补码编码来说,截断后的二进制序列与无符号编码是一样的,因此我们只需要多加一步,将无符号编码转换为补码编码就可以了。

因此对于无符号编码和补码来说,可以得到以下两个公式。

其它语言中的有符号与无符号

从上面的分析不难看出,具有有符号和无符号数的语言,可能会因此引起一些不必要的麻烦,而且无符号数除了能表示的最大值更大以外,似乎并没有太大的好处。因此有很多语言是不支持无符号数的。

比如LZ所使用的Java语言,就只有有符号数,这样省去了很多不必要的麻烦。无符号数很多时候只是为了表示一些无数值意义的标识,比如我们的内存地址,此时的无符号数就有点类似于数据库主键或者说键值对中的键值的概念,仅仅是一个标识而已。

文章小结

本文主要阐述了C语言当中的有符号数和无符号数,以及低位转高位的扩展、高位转低位的截断运算,下一章我们将讲解很重要的一节内容,整数的二进制运算。

深入理解计算机系统(2.4)---C语言的有符号与无符号、二进制整数的扩展与截断的更多相关文章

  1. 深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字

    上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言 ...

  2. CSAPP(深入理解计算机系统)读后感

    9月到10月8号,包括国庆七天,大概每天5小时以上的时间,把Computer System: A Programmer Perspective 2rd version(深入理解计算机系统)的英文版啃完 ...

  3. 【 c语言中无符号和有符号的加法运算】【深入理解】--【sky原创】

    原文:[ c语言中无符号和有符号的加法运算][深入理解]--[sky原创]   第一题 #include<stdio.h> int main() { unsigned int a=6; i ...

  4. 深入理解计算机系统(4.1)---X86的孪生兄弟,Y86指令体系结构

    引言 各位猿友们好,计算机系统系列很久没更新了,实在是抱歉之极.新的一年,为了给计算机系统系列添加一些新的元素,LZ将其更改为书的原名<深入理解计算机系统>.这本书非常厚,而且难度较高,L ...

  5. 《深入理解计算机系统》 Chapter 7 读书笔记

    <深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...

  6. 【转】《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误

    原文地址:http://blog.csdn.net/slvher/article/details/9150597 对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构 ...

  7. 《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误

    对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的模块跑起来后才出现内存崩溃,是很让人痛苦的.因为崩溃的位置在时间和空间上,通常是在距真正的错误源一段距离之后才 ...

  8. 深入理解计算机系统(1.1)------Hello World 是如何运行的

    上一篇序章我谈了谈 程序员为啥要懂底层计算机结构 ,有人赞同也有人反对,但是这并不影响 LZ 对深入理解计算机系统研究的热情.这篇博客以案例驱动的模式,通过跟踪一个简单 Hello World 程序的 ...

  9. 《深入理解计算机系统》【PDF】下载

    <深入理解计算机系统>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382303 内容提要 本书主要介绍了计算机系统的基本概念,包 ...

随机推荐

  1. 单页面实现之hash

    至学了angularJs后,发现这个单页面应用不知道在没有angularJs的情况下怎么实现. 所以就此对这个思考与资料并行,终于知道这个的实现基本原理. 首先angularJs的实现是hash值的变 ...

  2. x01.Weiqi.7: 调整重绘

    GitHub 谁方便谁拍,谁重要拍谁.在这个砖头满天飞的时代,一个好的生态显得尤为重要.  红颜小头发,要的很简单. 也许成绝唱,只因鱼断肠. 姚贝福娃的离去,除感叹人生无常外,活着做点有意义的事情, ...

  3. ModernUI教程:独立显示器DPI感知

             独立显示器DPI感知,是在Windows 8.1中新增的特性,这个特性针对拥有多个显示器同时各个显示器的DPI设定又不同的人.对这个新特性做了优化支持的软件能够在一个高DPI的显示器 ...

  4. Mvc视图引擎、寻址规则

    目前MVC中用的较多的视图引擎应该是WebFormViewEngine和RazorViewEngine了. 一个Request请求首先会进入Routing进行判断,对于错误的url是不能被路由匹配到的 ...

  5. Makefile 一点一滴(三)—— 尝试简单的变量替换

    上一版的 makefile: TestCpp : ./debug/TestCpp.o g++ -o TestCpp ./debug/TestCpp.o ./debug/TestCpp.o : ./sr ...

  6. ASP.NET MVC在线人数统计

    在Global.asax.cs文件中代码: protected void Application_Start() { Application[; AreaRegistration.RegisterAl ...

  7. ubuntu下安装wine1.8和阿里旺旺

    参考:http://www.linuxidc.com/Linux/2015-12/126722.htm和http://www.linuxidc.com/Linux/2016-05/131131.htm ...

  8. Windows Azure 如何学习Azure

    通过上一篇博文可以得知,Azure其实是个平台,上面跑的服务五花八门,可以相互分开使用,同时也可以相互结合. 那我们应该如何来学习Azure呢? 其实有很多种选择,正所谓条条大路通罗马, 官方的tra ...

  9. SerializationUtility

    public static T LoadFromXml<T>(string fileName) { FileStream fs = null; try { XmlSerializer se ...

  10. IOS基础之 (十一) 内存管理 ARC

    一 内存管理 1. set 方法内存管理的相关参数 retain: release旧值,retain新值(值适用于OC对象) assign:直接赋值(set方法默认,适用于非OC对象类型,即基本数据类 ...