C语言中数据的存储~

目录

1.整形(char)类型的存储;

2.奇奇怪怪的题目;

3.浮点数的存储与示例;


以下例子都是在32位机器下进行..

1.整形(char)类型的存储:

        <1>整形:

        在计算机中所有数字都是以二进制的补码形式存储。

原码:正整数的原码就是其二进制数字,其他位往前补0,例如123的二进制为:1111011

由于是在32位下,所以将其用0补齐,变成00000000 00000000 00000000 01111011

正整数的  原码 反码 补码 都是一样的!!!

        对于负数而言,其原码与整数的原码类似,只有一点不同,例如123的原码补齐后是

00000000 00000000 00000000 01111011,那么对于-123而言,他与整数的区别仅仅在于第一位的不同,那么-123的原码应该为10000000 00000000 00000000 01111011

        原码搞定后接下来就是 反码,规则就是首位(符号位不变)其他位取反(1变0,0变1),相应的,-123的反码应该为:11111111 11111111 11111111 10000100

        最后就是补码,补码就是将其反码+1,显然,-123的补码应该为:11111111 11111111 11111111 10000101

        <2>char 类型:

        将一个整数存储在char里面时,会发生截断就是把一个数的补码,只保留其最后八位,拿上面的的123来说,只保存0111011,其它与整形类似。

2.奇奇怪怪的题目

        T1:

1.

#include <stdio.h>
int main()
{
    char a= -1;
    signed char b=-1;
    unsigned char c=-1;
    printf("a=%d,b=%d,c=%d",a,b,c);
    return 0; 
}

        理由:a,b在内存中都是以补码存在,由于是有符号char类型,所以会发生阶段,只存了11111111 这个二进制序列,在使用时会发生整型提升,自动补齐剩下的位(补符号位,也就是1),最后以整形的方式打印,那么正好是-1;

        而对于c而言,他存储也是以11111111的形式存储,但是他是无符号char类型,那么在发生整形提升时会自动补0则最后提升为:00000000 000000000 000000000 111111111,由于是无符号,此时编译器认为他的原码反码补码相同,则最后解析该二进制序列就是255.

TIPS:所有无符号数在发生整型提升时通通补0!!!

        T2

        

#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0; 
}

        

         理由:

类似的,a要发生截断,而-128的补码是:11111111 11111111 11111111 10000000,发生截断以后储存在内存中的就是10000000,而最后要求以无符号整形的形式打印,那么他就会自动发生整形提升,会自动补齐符号位(1),那么它就变成了11111111 11111111 11111111 10000000,由于是用无符号整形来解析这个二进制序列,所以认为这个就是他的原码,则最后输出的就是这个很大的数字

 

        T3:

3.
#include <stdio.h>
int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0; 
}

显然,这个与上面的类似128的原码反码都是一样的 :00000000 00000000 00000000 10000000,发生截断以后,就变成1000000,这不是与上面的-128一样吗?那么解释就与T2一样。

T4:

int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j);

        解释:

数字的运算都是以补码的形式,由于最后是以整形形式来解析,就算j是一个无符号整数,他的加减和有符号相同,所以最后输出的-10就很容易想通了。

  T5 :

unsigned int i;
for(i = 9; i >= 0; i--) 
{
    printf("%u\n",i);
}

结果:死循环

        解释:

在i变成0之前,他都会正常的打印,因为都是无符号数,但是在i变为-1的时候,由于在内存中是以补码的形式存在,-1的补码为32个1,又是以无符号整形解析,那么此时认为32个1全部有效,则会变成一个很大的数字依次向下递减,最后变成-1的时候又与刚才类似,所以是一个死循环!

T6:

int main()
{
    char a[1000];
    int i;
    for(i=0; i<1000; i++)
   {
        a[i] = -1-i;
   }
    printf("%d",strlen(a));
    return 0; 
}

         解释:

strlen是测量数组长度的,在0(\0)的时候截止!

在解释之前,先讲解一下char short……等等一些数据储存的取值范围的讲解。

对于无符号char类型,他的二进制序列是一个A88的全排列,则从00000000变为11111111的一个过程,由于是无符号来解析,则认为他的所有位斗有效,而11111111解析过来正好是255,则无符号char类型的取值范围就是0~255;

 对于有符号char类型,他的二进制序列也是一个A88的全排列,也是从0000000变为11111111的一个过程,而由于他是一个有符号类型,则最高位1就是他的符号位,因此他的正整数最大取值就是01111111解析过来就是127,而对于111111111来说,他是以补码类型存储,那么他的原码就是10000001,解析过来就是-1,以此类推,它可以储存到-127,但是由于规定,最小值就应该存储的-128,所以有符号char,他的取值范围就是-128~127

则可以由此得出,有符号char类型的变化如下图:

则由题意,数组就会从0 -1 -2……一直到127 126…… 1 0,恰好是255个元素,上面就解释的通了,类似的可以得到short int的取值范围了。

T7 :

#include <stdio.h>
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

结果:死循环

解释:经过上面的解释,无符号char的取值范围是0~255,到256只有就会自动变为0,形成四虚幻

<3.浮点数的存储>

引入:

在一个32位的精度(float类型中),我们把第一位记为S,把后面八位记为E,把再后面二十三位记为M(64位,double类型只是E,M所占位数的区别)

S称为符号位,正数记为0,负数为1;

E称为指数位,M为有效数字位

例如,二进制数字:1068.5432可以与十进制类似记为1.0685432*2^3,E的存储就是把指数+127(double类型+1024),而M的存储是把1舍弃,存储后面的0685432,

两个特例:

如果指数全为1,则高达255次方,而2^32次方是42亿,显然2^255次方太大了,直接认为是无穷大量

如果指数为全0,此时就是-255次方,接近于0,则此时认为他就是0;

基于上面的理解,看如下代码:

int main()
{
	int n = 9;
	float* pFlo = (float*)&n;
	printf("n:%d\n", n);
	printf("*pFlo:%f\n", *pFlo);
	*pFlo = 9.0;
	printf("num:%d\n", n);
	printf("*pFlo:%f\n", *pFlo);
	return 0;
}

 解释:9就不用多解释了

对于0.000000来说,9在内存中的存储形式00000000 00000000 00000000 00001001,此时pFlo是一个浮点类型指针,对其进行解引用访问就会把上面的二进制序列自动解析为浮点序列,显然他的指数位为全0,则输出的就是0;

之后对*pFlo进行解引用访问为浮点类型9.0,根据上面的知识,他在内存中应该是0 10000010 001 0000 0000 0000 0000 0000这样存储,但是在打印的时候使用%d打印,则自动解析为上面的数字

打印9.0000则是一个正常的现象..

以上就是数据的存储

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值