有符号数和无符号数需要注意的细节问题

引言

最近我将自己平时工作中记录的一些问题点进行一个复盘或者说进行一个学习记录。今天记录的这个知识点,已经距离我工作入职第一次答辩5个月不到的时间了,这个点上,我依稀记得领导问的问题,出了一个C语言知识考,就是关于无符号数和有符号数的比较问题。下面就记录一下这个知识点。

定义

在计算机中,数值类型分为整数型或实数型,其中整型又分为无符类型或有符类型,而实型则只有符类型。 字符类型也分为有符和无符类型。

  • 有符号数:就是区分正负号的数呗,带+、-。如+5,-6;char型数据范围为:-127~+127
  • 无符号数:不区分正负号的数,没有符号位一说。char型数据范围为:0~255;

基本概念理解

原码

这个数的绝对值转换成对应的二进制数。(0和1构成的值)

  1. 对于正整数而言,取符号位为 0 ,后面直接加上真值的二进制表示即可
  2. 对于负整数而言,取符号位为 1,后面直接加上真值的绝对值的二进制表示即可

反码

将原码进行一位一位的取反得到的值(仅限于负数)。

需要注意如果是有符号的数,这里取反符号位不参与取反操作。

正数的反码为原码,负数的反码是原码符号位外按位取反。

补码

反码加1称为补码(仅限于负数)。

介绍一下负数补码的计算的方法:负数的补码 = 模 - |该数的绝对值|

这里模实际上就是一个最大的值,如8位的数据模就是2^8=256;

机器数

保存在计算机中的数字我们称为机器数,在计算机中用0或1 表示数字的符号 。也就是0和1组成的数。计算机并不会去关心它是什么类型的数,也没得符号一说。

真值

实际我们表示的数值,可以带符号,也可以不带符号,具体一定的数学意义。

举例理解说明

<pre data-language="c" id="GIc2F" class="ne-codeblock language-c" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959">例如针对有符号数的±2内存存储形式为

+2:0000 0010(原码)    
+2: 0000 0010(反码)
+2: 0000 0010(补码)

-2: 1000 0010(原码)
-2: 1111 1101(反码)
-2: 1111 1110(补码)
转换的核心:

正数的原码、反码、补码都是同一个!

负数的原码取出最高位为符号位1外,其余位按照其绝对值进行转换;

负数的反码等于除符号位外其余进行取反;

负数的补码等于反码加1!!

储存方式

我们需要明确一点,计算机内部对数据或者代码来说,最终都是以二进制数0和1存在计算机储存单元中的。对于数据来说,那对于正数和负数是如何区分的,我们需要思考,因为像上述的 1000 0010,在不清楚它怎么储存的,这个数可以表示是无符号数130,或者是有符号数-2,那就会产生这种分歧?

计算机中储存运算数据都是以补码的形式储存的!!!不用关心它是啥类型的数据,实际上,计算机本质上也是不会区分有符号和无符号的,都是一样的,对于计算机来说。

举例说明:

单纯从一个字节8位二进制存储上来看,1111 1111 既可以表示有符号的-1又可以表示无符号的255。计算机里面就是这种理解,当然实际是有无符号还需要我们如何去定义的类型。

大小比较

先看一下如果将一个有符号数和无符号数进行比较会产生什么结果?(领导考我的题)

#include<stdio.h>
void main()
{
   unsigned int a = 2;
   int b = -5;

    if(a > b )
    {
          printf("a > b, a = %u, b = %d\n", a, b); 
    }
    else
    {
          printf("a <= b, a = %u, b = %d\n", a, b); 
    }
}

我们直观从数学的角度看,结果肯定是会是

a > b, a = 2, b = -5

但是运行后结果为:

image

为啥嘞,这个就是我们容易忽视的一个细节,简单分析,根据上述铺垫的基础知识。

在C语言中,进行混合运算时,编译系统遵循一定规则,完成数据类型的自动转换,即隐式类型转换。一般是占用内存字节数少类型,向占用内存字节数多的类型进行转换,(这里是指数值大小)以防止精度丢失。

unsigned int与int相比,拥有更大的正数范围。所以,无符号数与有符号数进行运算时,先需要将有符号数转化为无符号数进行操作。

需要注意一点:处理同样字长的有符号数和无符号数之间的相互转换的一般规则是:数值可能会改变,但是位模式不变。也就是说,将unsigned int强制类型转换成int,或将int转换成unsigned int底层的位表示保持不变。

在上述例子中:

a=2(变量a的值:0000 0000 0000 0000 0000 0000 0000 0010)值为2;

b=-5(变量b的值: 1111 1111 1111 1111 1111 1111 1111 1011)这个有符号数强制转换成无符号数

(1111 1111 1111 1111 1111 1111 1111 1011= 4,294,967,291,

从二进制来看,4,294,967,291>2,故b>a;

再次验证一下上述的结论:

#include<stdio.h>
//C语言中没有直接输出二进制的定义,如果要输出二进制数需要我们自己定义输出,下面输出十六进制数
void Display_Hex(unsigned char *date, int leng)
{
    int i;
    for(i=0; i<leng; ++i)
    {
        printf("%.2x   ",date[i]);
    }
    printf("\n\r");
}


void main()
{
   unsigned int a = 4294967291; //这个值如果是看成有符号的已经大于了最大值
   int b = -5;
    printf(" a = %d, a = %u \n",a,a);
    printf(" b = %d, b = %u \n",b,b);

    Display_Hex((unsigned char*)&a, sizeof(a));//打印出a的十六进制数
    Display_Hex((unsigned char*)&a, sizeof(b));//打印出b的十六进制数
}</pre>

运行结果:

image

可以看出来有符号的数4294967291和-5储存上是一样的,这也解释了上面进行比较时-5被转换成了无符号数参与了比较,所以结果不是我们直观理解的那种。

总结

通过上面的论证和这个问题的产生,那总结一下。

  • 无符号数和有符号数不进行大小比较

  • 类型不同的数据进行数学运算需要注意合理性,特别是减法哦,无符号的减需谨慎。

  • 实际上,这里的数据大小情况,可以类比坐标系中的360度角度问题一样,-30度和330度是一样的位置。

对于无符号数来说,数值达到最大值后,超了那就从0又开始数了;

对于有符号数来说,数值达到最大值后,超了那就从-(最大值)开始数了;

欢迎关注本人微信公众号:那个混子
记录自己学习的过程,分享乐趣、技术、想法、感悟、情感!
单片机类嵌入式交流学习可加企鹅群:120653336
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容