原码反码补码详解 -浮点数的表示方法 -数据截断、溢出和提升(全网最全)_浮点小数的二进制补码(1)

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取


四、溢出和截断,数据类型的转换

首先我们将C语言中所有的基本数值数据都列举出来,来看看它们之间的运算转换。

  1. 整形类的

    • 有符号数:char, short, int, long
    • 无符号数:unsigned char, unsigned short, unsigned int, unsigned long
  2. 浮点类的

    • float,double

不同数值类型之间的运算

一般我们都是对相同数据类型的数值之间进行+,-,*,/运算。比如:int和int之间进行加减乘除运算,但是不同数据类型之间进行加减乘除运算也是很常见的。下面我们就来了解一下不同数据类型之间运算的规则。

  1. 若一个运算符两侧的数据类型不同,则先自动进行类型转换,使两者具有同一类型,然后进行运算。
  2. 自动类型转换的规则是将低精度的数据转换成高精度的数据

数据低精度和高精度的概念:对于整型数据char的精度最低,long的精度最高

整型数据之间的精度由低到高排序为:char < short < int < long

浮点数据之间的精度由低到高排序为:float < double

任何整型的数据精度都小于浮点数据,因此总的数据类型精度排序为:char < short < int < long < float < double

上面的排序还没有考虑到无符号数的精度排序,因为无符号数这边稍微有点复杂我们后面再单独讲。
3. 具体运算规则:

* 当两个不同整型数据类型进行运算时,将低精度的整型数据转换成高精度的整型数据再进行运算;
* 当整型和浮点型进行运算,不管浮点是float还是double,都将进行运算的整型和浮点转成double进行运算;
* Char型与int型数据进行运算,就是把字符的ASCII码与整型数据进行运算

 如:12+‘A’=12+65=77
* 两个int型相除,不管是否有余数,结果都为整型;如:5/10 输出是整数部分:0

下面我们用代码来测试一下:

#include <stdio.h>
int main ()
{
	char a1 = 'A', a2 = 'B';
	short s1 = 55, s2 = 66;
	int i1 = 555, i2 = 666;
	float f1 = 2.72, f2 = 22.72;
	double d1 = 3.14, d2 = 31.45;
	
    printf("%d",sizeof(X));
}

sizeof(char) = 1 sizeof(short) = 2 sizeof(int) = 4 sizeof(float) = 4 sizeof(double) = 8

sizeof(a1 + a2) = 4 两个char相加后变成了int,4个字节

sizeof(a1 + s1) = 4 char和short相加变成了int,4个字节

sizeof(s1 + s2) = 4 short和short相加变成了int,4个字节

sizeof(a1 + i1) = 4 char和int相加变成了int,4个字节

sizeof(i1 + i2) = 4 int和int相加变成了int,4个字节

sizeof(i1 + f1) = 4 float和float相加变成了float,4个字节

sizeof(i1 + d1) = 8 int和double相加变成了double,8个字节

sizeof(a1 + d1) = 8 char和double相加变成了double,8个字节

可以看出,当不同整型数据运算时,都优先向int转换;当涉及到浮点数时,则转成浮点数。

整型提升是C程序设计语言中的一项规定:在表达式计算时,各种整形首先要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型;然后执行表达式的运算。


数据的溢出、截断、提升

**溢出:**指给某个变量赋值时,超出了该类型变量所能表达的范围,比如:

unsigned char a;
a = 260;//a的取值范围是0~255,使a=260就会导致数据溢出,a最终得到的是一个错误的值;

对于整型溢出,分为无符号整型溢出和有符号整型溢出。

对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))作模运算”,也就是说,如果一个unsigned char(1字符,8bits)溢出了,会把溢出的值与256求模。例如:

unsigned char x = 0xff;
printf("%d\n", ++x);

对于signed整型的溢出,C的规范定义是“undefined behavior”,也就是说,编译器爱怎么实现就怎么实现。对于大多数编译器来说,算得啥就是啥。比如:

signed char x =0x7f; //注:0xff就是-1了,因为最高位是1也就是负数了
printf("%d\n", ++x);

上面的代码会输出:-128,因为0x7f + 0x01得到0x80,也就是二进制的1000 0000,符号位为1,负数,后面为全0,就是负的最小数,即-128。

另外,千万别以为signed整型溢出就是负数,这个是不定的。比如:

signed char x = 0x7f;
signed char y = 0x05;
signed char r = x \* y;
printf("%d\n", r);


提升:提升是将占字节小的元素赋给占字节大的元素时出现的补位现象。

#include <stdio.h>
int main ()
{
    char a = -50;//a的补码为11001110
    short b = a;
    int c = a;
    
	printf("%d\n",b);//打印值为-50,补码为11111111 11001110
	printf("%d\n",c);//打印值为-50,补码为11111111 11111111 11111111 11001110
}

可以看出对于负数来说,提升是使用低位填充,高位补1的操作。

对于正数,则是低位填充,高位补0的操作。

#include <stdio.h>
int main ()
{
    char a = 50;//a的补码为 00110010
    short b = a;
    int c = a;
    
	printf("%d\n",b);//打印值为50,补码为00000000 00110010
	printf("%d\n",c);//打印值为50,补码为00000000 00000000 00000000 00110010
}


截断:指给某个变量赋值时,超出了该类型能表达的范围,如果采取截断策略,则变量只保留数据中低字节的数据,高字节的数据则会丢弃,即截断是将所占字节大的元素赋给所占字节小的元素时会出现数值的舍去现象。比如

#include <stdio.h>
int main ()
{
	int a = 1431655765; //a的补码为01010101 01010101 10110101 01010101
	short b = a;
	char c = a;
	printf("%d\n",b);//b打印的值为-19115,二进制补码为10110101 01010101
	printf("%d\n",c);//c打印的值为85,二进制补码为01010101
}

可以看出截断的规则是先填充低位,截断高位。


五、联合体实例

下面我们以联合体为例,来讲解一下上面知识的应用。

首先看两段代码:

#include <stdio.h>
union UN
{
	char c;
	int i;
};
int main ()
{
    UN test = {555};
    printf("%d\n",test.i); //打印的test.i的值为43
}

#include <stdio.h>
union UN
{
	int i;
	char c;
};
int main ()
{
    UN test = {555};
    printf("%d\n",test.i);//打印的test.i的值为555
}

上面两段代码就只有联合体UN内部的char和int元素定义的顺序发生了一下变化而已。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

eO711jAB-1715545436163)]
[外链图片转存中…(img-hcJfXnrt-1715545436163)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值