精华内容
下载资源
问答
  • C语言的有符号与无符号,二进制整数扩展与截断     前一节说了整数表示方式,,也就是无符号编码与补码编码.这一届说一下二进制整数扩展与截断,这部分内容与C语言挂钩.so,我们先看以下C语言有符号和无符号...

    C语言的有符号与无符号,二进制整数的扩展与截断

     

     

    前一节说了整数的表示方式,,也就是无符号编码与补码编码.这一届说一下二进制整数的扩展与截断,这部分内容与C语言挂钩.so,我们先看以下C语言的有符号和无符号数.

     

     

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

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

     

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

    #include <stdio.h>

     

    int main(){

        short i = -12345;

        unsigned short u = i;

        printf("%d %d\n",i,u);

    }

     

    你自己观察一下输出结果你就会发现,一个负数变成了正数,再看下面这个程序,他展示了在进行关系运算时,由于有符号数和无符号数的隐式转换所导致的违背常规的结果.

    #include <stdio.h>

     

    void main(){

        printf("%d\n",-1 < 0U);

        printf("%d\n",-12345 < 12345U);

    }

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

     

     

     

    扩展

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

     

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

     

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

     

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

     

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

     

     

     

     

     

     

    截断

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

     

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

     

     

     

     

    对与补码编码来说,截断后的二进制序列与无符号编码是一样的,因此我们只需要多加一步,将无符号编码转换为补码编码就好了.因此对于无符号编码和补码来说,可以得到以下两个公式.

     

     

     

     

     

    其他语言中的有符号和无符号

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

    我接触过的C#JAVA就只有有符号数,这样省去了很多不必要的麻烦.无符号数很多时候只是为了表示一些无数值意义的标识,比如我们的内存地址,此时的无符号数有点类似数据库主键或者说键值对中的键值的概念,仅仅是一个标识而已.

     

    小结

     

    低位转高位叫扩展,高位转低位叫做截断.

     

     

     

     

    展开全文
  • 只说最精华的: ...3. 有符号型和无符号型变量的区别在于二进制首位是否作为符号位:有符号型,首位最为符号位,0表示正,1表示负; 无符号型,首位和其他位一样作为数字位。 4. C语言中,变量...

     只说最精华的:

    1. 整数在内存中是以补码得形式存储的 (补充说明一下:为什么补码? 计算机只有0和1,-5这个数怎么存,计算机中可没有“-”,需要用0和1来表示符号)
    2. 计算机中的加、减法运算本质上都是二进制的加法

    3. 有符号型和无符号型变量的区别在于二进制首位是否作为符号位:有符号型,首位最为符号位,0表示正,1表示负; 无符号型,首位和其他位一样作为数字位。

    4. C语言中,变量赋值时存在“位截取”,如char c = 0xffff1234; 在赋值时,是截取最后8bit二进制数,即 c= 0x34

     

    下面贴一段代码,验证一下,就全明白了:

    		unsigned char tt1 = 0xff;
    		unsigned char tt2 = 5;
    		unsigned char sum = tt1+tt2;
    		printf("\n%d\t%x\n%d\t%x\n", sum, sum, tt1+tt2, tt1+tt2);

     

    结果显示:

            4       4

            260   104

     

    总结一句话:

    计算机的世界,一切都是0和1;永远只有加法,没有减法!

    展开全文
  • 详细分析区别的产生原因3.1 无符号(unsigned)int型最大值3.2 unsigned int最大值赋值给int变化3.3 无符号与有符号类型对溢出处理区别3.4 负数赋值给无符号类型变化3.5 -0和+0实际储存方式3.6 “-0”...

    写在前面:这篇只分析4字节整数(就是int和unsigned int),我会在笔记-4中对其他情况作出分析(此外注意,无符号是没有小数的)。

    1. 无符号数与有符号数的定义

    简单来讲,无符号数就是所有的二进制位都是数值位,而有符号数的最高位为符号位,0表示正,1表示负,而剩下的位数才是数值位。此外要注意的是,无符号数只有整数,由于没有符号,因此也可以理解为是正整数,通常用于表示地址,大小之类。

    2. 通过代码展示两者的区别

    以c++中4个字节大小的int和unsigned修饰的无符号int类型为例,尝试声明如下变量(用16进制赋值也行):

    	int t = 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2;//2的8次方
    	unsigned int unsigned_i = t*t*t*t-1;//2的32次方-1,即理论上4个字节无符号整数的最大值
    	int j = t * t * t * t -1;//有符号整数下,这个数溢出了
    	unsigned int unsigned_j = j;//看一下变成啥了
    	int h = t * t * t * t;//无符号时最高位应是1,有符号下只取31位因此变成了0
    	unsigned int unsigned_h = h;//侧面证明确实是0,最高位的1被抛弃了,并没有保留
    	int k = - 1;//有符号下,-1的实际二进制储存方式跟想象中有些许区别
    	unsigned int unsigned_k = k;//转换成无符号数,可以发现-1变得很离谱
    

    把所有变量打印之后的结果如下图所示:
    在这里插入图片描述

    3. 详细分析区别的产生原因

    来具体分析一下这张图体现出了什么:

    3.1 无符号(unsigned)int型的最大值

    1. unsigned_i 赋值为232-1,它是int能表示的最大值,即11111111 11111111 11111111 11111111 (每个位置都是数值位),这个写法有两种解释方法:(1)1 00000000 00000000 00000000 00000000 - 1正好就是111…;(2)32个位置,每个位置有2个状态,共有232个状态,每个状态可以表示一个数字,因此最多连续表示232个十进制数,从0开始数232个数是232-1。

    3.2 unsigned int最大值赋值给int的变化

    1. j 的赋值与unsigned_i 相同,但是打印出来是-1,这个的原因是,有符号数的最高位是符号位,剩下的才是数值位,因此,在计算过程中,txtxtxt这部分(即232)只保留了31个位置,而由于232是第33个位置为1,其余都是0,只保留31个位置后只剩下0,0再减-1得-1。

    3.3 无符号与有符号类型对溢出的处理区别

    下面举个例子证明一下这个现象:
    
    int j1 = t * t * t * (t / 2) - 1;//2的31次方-1,即理论上4个字节有符号整数的最大值
    int j2 = t * t * t * t / 2 - 1;//跟j1的区别就是没括起来,结果就成-1了
    int j3 = t * t * t * t/20000 -1 ;//即使除以一个很大的数也还是一样是-1
    

    把所有变量打印之后的结果如下图所示:
    在这里插入图片描述
    可见,j1(231-1)可以正确打印出有符号int的最大值,而j2却还是打印出了-1,这证明了有符号整数在计算过程中,任何一步溢出了,都会影响后续结果,而不像无符号整数,只要全部计算完后的结果没有溢出即可。

    然而这里有一个疑问,为什么无符号与有符号在这方面有所区别呢?(即溢出的不同处理)我想这可能有一定设计的理由吧,这里写出来作为提醒。

    3.4 负数赋值给无符号类型的变化

    1. unsigned_j 是 j 在无符号情况下的数值,可以看到,j是-1,但unsigned_j 与unsigned_i的大小是相同的,即unsigned_j 为最大值1111…(32个1),这是因为,负数在计算机内是以补码的形式储存的。

      举个例子,若一个数值由4位组成,则-1为1001(最高位1代表负数),反码是1110,补码是1111,正好是无符号时的最大值。因此,这就是unsigned_j与 unsigned_i大小相同的原因。

    3.5 -0和+0的实际储存方式

    1. h为0的原因不再赘述了,将h赋值给unsigned_h后结果也为0,可见确实是0(且最高位不是1),此外,如果试一下会发现(这里就不贴代码了),无论企图通过什么方式给无符号整数变量赋值-0,得到的结果都是0,也就是说,-0和0的最高位都是0,-0的最高位也不是1。

    3.6 “-0”的真实数值

    1. 通过4,我们知道-0不是1000…,那么10000…是什么呢?打印一下看看:
    unsigned int n = t * t * t * (t / 2);//2的31次方
    int m = n;
    

    在这里插入图片描述
    可见,当把一个无符号的231(最高位为1,其余为0)赋值给有符号32位整数时,结果并不是-0,而是-231,正常情况下,32位里31位是数值位,最小能表示到-(231-1)=-231+1,最大能表示到231-1,这里用10000…(正常情况下的-0)来表示-231+1-1=-232,就可以多表示一个数,但最大值还是231-1啊要注意。(这里多表示了一个负数,想来应该是因为最高位为1吧)

    3.7 有符号整数的-1,是无符号整数的最大值

    1. k和unsigned_k这种把-1赋值给无符号整数的情况,在3里已经分析过了,这里不再赘述。

    4. 总结&补充(重要)

    1. 在某些编译环境下,将无符号类型赋值给有符号类型只会警告,不会报错也不影响编译进行,因此,如果不了解两者的区别而互相乱赋值的话,有可能会引起一些不好察觉的bug,所以建议还是区分开。

    2. 本篇文章只针对了4个字节的整数,没有涉及到浮点数赋值给无符号整数的情况,也没有涉及2个字节的变量赋值给4个字节之类的,因此举例的代码可以直接把int赋值给unsigned,然而在其他情况下,这样直接赋值可能会由于编译器内的隐式转换,而无法展现出想要的结果,会在下一篇笔记-4中对其他情况进行分析。这里提出来,是再次强调一下,本篇只针对4字节整数啊!

    3. 文中所有赋值都可以用16进制来写,看着更直接点,但是这篇写的时候没想到这部分内容能写那么多东西,测试代码都是随便写的,就…

    展开全文
  • n位二进制有符号数据补码表示范围:[−2n−1,2n−1−1][-2^{n-1} ,2^{n-1}-1][−2n−1,2n−1−1]。 n位二进制无符号数据(正数)补码(三码相同)表示范围:[0,2n−1][0 ,2^{n}-1][0,2n−1]。 6.补码补码是...

    1.正数原码、反码、补码均完全一样

    2.负数反码符号位不变,其它位取反

    3.负数补码符号位不变,其它位取反,最后加1

    4.计算机采用补码方式来储存数据。

    5.n位二进制有符号数据的补码表示范围:[2n1,2n11][-2^{n-1} ,2^{n-1}-1]
    n位二进制无符号数据(正数)的补码(三码相同)表示范围:[0,2n1][0 ,2^{n}-1]

    6.补码的补码是原码。

    7.负数的原码和补码互相转换简单方法:从原码(或补码)的右边往左开始数,第一个不是0的后边的每一位数取反即是它的补码(或原码),符号位不变,还是“1”。

    展开全文
  • 在内存中存是其对应二进制补码 char(存在内存中是其ASCLL码) short(短整型) int(整形) long(长整形) 2,浮点型: float double long double(不是所有编译器都支持) 3,构造类型(自定义类型) 数组 结构体...
  • 将一个数二进制位右移N位,移到右端低位被舍弃,对于无符号数,高位补0。 & 按位 如果两个相应的二进制位都为1,则该位结果值为1,否则为0。 l 按位或 两个相应的二进制位中只要一个为1,该位...
  • **原码:**一个数原码(原始的二进制码)如下特点: 最高位做为符号位,0表示正,为1表示负 其它数值部分就是数值本身绝对值的二进制数 负数原码是在其绝对值基础上,最高位变为1 **反码:**对于正数,反码...
  • 本篇是10_二进制中1的个数的...normal使用的是循环移位,因为考虑到有符号数负数右移,左边空位补1的情况,因此定义了一个无符号的flag初始化为1,并让flag循环左移,输入相与,便能得到输入中1的个数。这种办法属...
  • 位 字节 INT 有符号无符号

    千次阅读 2018-10-23 11:24:36
    位(bit): 位,又称比特位,英文是BIT。表示意义是一个位,也就是1或者0。 字节(byte): 字节,又称8位二进制,英文是byte。...有符号与无符号区别就是有符号通过首位定义来区分正数与负数。主要是数...
  • 对一个无符号数,先求其反码(按位取反之意,与有符号数中定义反码表示是不相同),然后从低位到高位,按位相加,等于2则进1,若最高位有进位,需要向最低位加1。 在这个定义中,补码加法有些区别的是,若最高...
  • 有符号与无符号位最明显的区别就是二者的表示范围不同。 (无符号数: 0 ----------------- 255 、有符号数: -128 --------- 0 ---------- 127 ) 原码: 最高位是符号位,0代表正数,1代表负数,非符号位为改...
  • charbyte的区别

    2019-01-25 15:23:34
    byte 是字节数据类型 ,是有符号...char是一个16位二进制的Unicode字符,JAVA用char来表示一个字符 。 下面用实例来比较一下二者的区别: 1、Char是无符号型的,可以表示一个整数,不能表示负数;而byte是有符号...
  • bytechar的区别

    千次阅读 2018-02-08 10:52:49
    byte 是字节数据类型 ,...char是一个16位二进制的Unicode字符,JAVA用char来表示一个字符 。 下面用实例来比较一下二者的区别: 1、Char是无符号型的,可以表示一个整数,不能表示负数;而byte是有符号型的,可以
  • charbyte的区别介绍

    2019-08-14 10:49:56
    摘要: byte 是字节数据类型 ,是...char是一个16位二进制的Unicode字符,JAVA用char来表示一个字符 。 1、Char是无符号,可以表示一个整数,不能表示负数;而byte是有符号,可以表示-128—127 数;如...
  • char byte的区别

    2016-04-21 10:02:34
    不是经常用,脑补一下以前的基础知识! byte 是字节数据类型 ,是有符号型的,占1 ...char是一个16位二进制的Unicode字符,JAVA用char来表示一个字符 。 下面用实例来比较一下二者的区别: 1、Char是符...
  • Java基础篇 charbyte的区别

    万次阅读 2018-10-11 22:56:14
    byte 是字节数据类型 ,是有符号,占1 个字节;大小范围为-128—127 。char 是字符数据类型 ,是无符号,占2字节(Unicode码 );大小范围 是0—65535 ;char是一个16位二进制的Unicode字符,JAVA用...
  • 单片机CYOV的区别

    千次阅读 2013-11-13 13:07:51
    OV: 表示运算过程中是否发生了溢出,若运算结果超过了8位二进制数所能表示数据范围即有符号数-128~+127,则标志位置1。 对无符号运算,判断只需CY即可,OV无作用。 对有符号运算,OV位是有用。...
  • byte是字节数据类型,是有符号,占1个字节;大小范围为-128—127 。char是字符数据类型,是无符号,占2字节(Unicode码);大小范围是0—65535;char是一个16位二进制的Unicode字符,JAVA用char来表示一个...
  • 在理解byte转int时需要0xff原因之前,需要明白三个基础知识点: 计算机是以补码形式储存数字 正数补码是它自身,负数补码...基本数据类型包括有符号数据类型和无符号数据类型,当数据由低精度类型转变...
  • 相信很多初学者,虽然知道怎么用char 和byte ,但是对他们之间的区别却不甚了解首先 byte 是字节数据类型 ,是有符号型的,占1 个字节;大小范围为-128—127 。char 是字符数据类型 ,是无符号型的,占2字节(Unicode...
  • byte 是字节数据类型 ,是有符号,占1 个字节;大小范围为-128—127 。char 是字符数据类型 ,是无符号,占2字节(Unicode码 );大小范围 是0—65535 ;char是一个16位二进制的Unicode字符,JAVA用...
  • 一起学习C语言:C语言数据类型()

    千次阅读 2020-01-31 00:21:01
      上一篇<一起学习C语言:C语言数据类型(一)>...1.2.2 无符号类型与有符号类型的区别 1.2.3 短整型、整形以及长整形的区别 1.2.4 整形 1.2.5 长整形 1.2.6 判断类型字节长度 1.2.7 八进制、...
  • 有符号数:它与无符号的区别,w位二进制值,第一位表示符号位,0表示整数,1表示负数,后面w-1位表示数值; 原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值 反码: 正数的反码是其本身 负数...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 136
精华内容 54
关键字:

二进制有符号与无符号的区别