数据在内存中的储存

 

一,数据类型的介绍

1.基本的内置类型:分为signed, unsigned(默认有符号数)

 

char:字符数据类型(1byte),有符号数的大小范围是-128~127,无符号数是0~255.

short:短整型(2byte),有符号数的大小范围是-2^15~2^15-1,无符号数是0~2^16-1.

int:整形(4byte),有符号数的大小范围是-2^31~2^31-1,无符号数是0~2^32-1.

long:长整形(4byte),有符号数的大小范围是-2^31~2^31-1,无符号数是0~2^32-1.

long long:更长整形(8byte),有符号数的大小范围是-2^63~2^63-1,无符号数是0~2^64-1.

float:单精度浮点数(4byte),有符号数的大小范围是-2^31~2^31-1,无符号数是0~2^32-1.

double:双精度浮点数(8byte),有符号数的大小范围是-2^63~2^63-1,无符号数是0~2^64-1.

 

类型的意义:类型的开辟决定了内存空间的大小,如何看待内存空间的大小

 

2.构造类型

 

数组类型,结构体类型(struct),枚举类型(enum),联合类型(union),自定义类型

 

3.指针类型 (int *)

 

   空类型(void):通常同于函数的返回类型,函数的参数,指针类型

 

二,整形在内存中的存储(存放的是补码

 

无符号数:是正数,补码就是原码;

 

有符号数:最高比特位为符号位,1表示负数,0表示整数;补码=(原码变成反码)+1;

 

在储存数据时,首先看类型(有无符号位),再看正负(最高比特位),最后储存数据;

 

在读取数据时,首先看类型(有无符号位),再看正负(最高比特位),最后读取数据;

 

三,大端小端的介绍

 

1,端模式:数据位保存在地址中,数据的位存在地址中;

 

2,端模式:数据的位保存在地址中,高位保存在高地址中;

 

从下面的程序判断是大端还是小端:

 

 

#include<stdio.h>
#include<windows.h>
int check_sys()
{
	int i = 1;
	return(*(char *)&i);//(char*)&i 强转成char*类型,再解引用就是首地址(低地址);
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("xiaoduan\n");
	}
	else{
		printf("daduan\n");
	}
	system("pause");
	return 0;
}

 

 

i (0000 0001) 强制转化为char *;低位是1,首地址是低地址,则是小端。

下面是整形在内存中储存的练习:

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;
}

 

 

 

首先看char a是有符号char类型,占1byte

 

 

a=-1;a的原码为1000 0001,但是在计算机内存补码,所以需要转化为补码:反码 1111 11110,补码=反码+1为 1111 1111

再看输出的a=%d,是有符号整形,这时需要填充(填充时看变量自身的类型,无符号数填充0,有符号数看最高符号位

 

填充后为1111 1111 1111 1111 1111 1111 1111 1111

输出有符号整形:补码-1变反码  1111 1111 1111 1111 1111 1111 1111 1110

 

                                                 1000 0000 0000 0000 0000 0000 0000 0001

 

则a=-1; 同理b=-1;

 

 

 

unsighed char c 是无符号char类型,占1byte;

 

c=-1,原码是1000 0001,在计算机存补码:1111 1111

 

输出的是c=%d,需要填充,这时变量c是无符号,则填充后为: 0000 0000 0000  0000  0000  0000 1111 1111

 

这时补码是个正数,原码=补码,则c=255;

 

2,把第一题代码不变,只改变输出,结果是什么

 

printf(“a=%u,b=%u,c=%u”,a,b,c);

 

a=%u输出的是无符号整形,也需要填充(变量a是有符号char)1111 1111 1111 1111 1111 1111 1111 1111

 

因为是无符号整形,则补码是正数,所以原码=补码,即输出结果为2^32-1;同理b=2^32-1;

 

c=%u输出的是无符号整形,需要填充(变量c是无符号)0000 0000 0000 0000 0000 0000 1111 1111,即输出c=2^8-1=255.

 

3,

 

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

 

char a是有符号char类型,a=-128 原码是1 1000 0000

 

                                                     反码是1  0111 1111

 

                                                      补码是1 1000 0000

 

由于char占1byte , 存在计算机的是1000 0000;

 

 

输出的a=%u,是无符号整形,需要填充(a变量是有符号) 1111 1111 1111 1111 1111 1111 1000 0000

 

 

输出无符号则说明补码是正数,所以原码=补码,输出a=2^31+2^30+.......+2^7=4294967168;

 

 

4,

 

#include<stdio.h>
int main()
{
    unsigned int i;
    for(i=9;i>=0;i++)
   {
     printf("%u\n",i);
   }
     return 0;
}

 

unsigned int是无符号整形,即是正数(i>=0),说明for条件永成立,当i=-1时,计算机会默认为无符号数

 

所以这个结果是死循环。

 

5,

 

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

 

 

 

当i=0时,a[0]=-1

 

 

当i=127时,a[127]=-1+(-127)=-128

 

 

-1在计算机存补码是1111 1111; -127  原码是 1111 1111,反码1000 0000,补码是1000 0001

 

 

1111 1111+1000 0001=1 1000 0000,则-1+(-127 )在计算机存1000 0000,即-128;

 

 

当i=128时,a[128]=-1+(-128)=127

 

 

-128 原码是1 1000 0000 ,反码是1 0111 1111,补码是1000 0000

 

 

1111 1111+1000 0000=1 0111 1111,则-1+(-128)在计算机存的是0111 1111,即127

 

 

当i=129时,a[129]=-1+(-129)=126

 

 

-129 的原码是1 1000 0001,反码是1 0111 1110,补码是1 0111 1111

1111 1111+1 0111 1111=10 0111 1110,则-1+(-129)在计算机存的是0111 1110,即126

 

像这样一直到结果为0结束。

 

从上面可以看出存的数有-1~-128,127~0;但是strlen不统计‘\0’,则共有255个空间。

 

6,

 

short num=32767;
short int a=num+1;
printf("%d\n",a);

 

 

 

32767化成二进制位0111 1111 1111 1111,加1->1000 0000 0000 0000

 

 

系统直接识别为最小值 ,不进行解码,结果为-32768.

三,浮点数在内存中的存储

 

1,浮点数在计算机内以二进制浮点数表示:(-1)^s*M*2^E

 

 

(-1)^s表示符号位,当s=0时,浮点数为正数,当s=1时,浮点数为负数;

 

 

M表示有效数字(小数点后面),大于等于1,小于2;

2^E表示指数位;

 

2,规定:对于32位的浮点数,最高的一位是符号位s,接着的八位是指数E,剩下的23位为有效数字M;

              对于64位的浮点数,最高的一位是符号位s,接着的11位是指数E,剩下的52位为有效数字M;

 

3,下面看一个例子:

 

#include<stdio.h>
#include<windows.h>
int main()
{ 
	int n = 9;
	float *p = (float *)&n;
	printf("n的值:%d\n", n);
	printf("*p的值:%f\n", *p);
	system("pause");
	return 0;
}

 

输出结果是:

 

为什么把9变成浮点数就成了0.000000呢?

 

首先把9写成二进制0000 0000 0000 0000 0000 0000 0000 1001

 

它的符号位是s=0,指数部分为E=0000  0000(-127),后23位为有效数字M=000 0000 0000 0000 0000 1001

则浮点数就可以写成二进制数(-1)^0*0.000 0000 0000 0000 0000 1001*2^(-127)=1.001*2^(-127),这个浮点数是接近0的正数,所以表示成十进制小数为0.000000

 

 

 

 

 

 



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值