数据的存储进阶

1.大小端问题


大端字节序的概念是,把一个数据低位字节处的数据放在高地址处,高位字节处的数据放在低地址处   
小端字节序的概念是,把一个数据低位字节处的数据放在低地址处,高位字节处的数据放在高地址处   


举个例子 123,1是高位   百位, 3 是低位   个位
 

设计一个小程序来判断当前机器的字节序

int main()
{
	int i = 1;
	//00000000000000000000000000000001
	/*0x 00 00 00 01*/

	//大段 00 00 00 01
	//小段 01 00 00 00
	char* p = (char*)&i;   /*判断大小端取出第一位判断*/
	if (*p == 1)
	{
		printf("小段");
	}
	else if (*p == 0)
	{
		printf("大段");
	}
   
	return 0;
}

在32位大端模式处理器上变量b等于( )
unsigned int a= 0x1234;
unsigned char b = *(unsigned char *)&a;

大端存储  00 00  12  34,在int中是这样存的,正着存是大端(高位在低地址,低位在高地址)

强制类型转化成char类型,只能访问一个字节,只能访问前面的00 

结果就是0x00

2.整形在内存中的存储

 下面是有符号char的范围和无符号char的范围,char是1个字节,8个比特位.

有符号char的范围是-128到127,无符号char的范围是0到255



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

这样的题画图做,有符号char的范围是 -128到127   , 127+1成了-128了 

-1到-128之间有128个,1到127有127个,加一起是255,这是数组下标

 3. int类型下无符号整形里面放负数的情况

int main()
{
	unsigned int i = -10;

	//10000000000000000000000000001010
    //11111111111111111111111111110101
	//11111111111111111111111111110110   补码

	printf("%u\n", i);    
	//虽然无符号数里面可以放负数,但是打印出来的数不是负数
	//这里打印无符号数,无符号数的原反补一样跟正数一样
	//补码11111111111111111111111111110110 也是原码直接打印
	//4, 294, 967, 286
}
int main()
{
	unsigned int i = -10;

	//10000000000000000000000000001010
	//11111111111111111111111111110101
	//11111111111111111111111111110110   补码

	printf("%d\n", i);
	//%u是打印无符号数,意思是你要我打印的一定是无符号数,不是无符号数,我也认为是无符号数
   //‰d是打印有符号数,意思是你要我打印的一定是有符号数,不是有符号的数,我也认为是有符号数
	//这个结果是-10,看成有符号数算,补码转化成原码再进行打印
}

4.char类型下%d的打印(要进行整形提升) 

   (%d打印的是一个有符号整数)

int main()
{
	char a = -1;
	signed char b = -1;
	//10000000000000000000000000000001   原
	//11111111111111111111111111111110   反
	//11111111111111111111111111111111   补

	//%d就意味着打印一个整形,而char类型不够一个整形,进行整形提升
	//char类型8个比特位最多可以放11111111
	//整形提升,补符号位,11111111.符号位是1,前面都补1
	// 
	//11111111111111111111111111111111 补码   打印的是原码,再转换成原码
	//10000000000000000000000000000000 
	//10000000000000000000000000000001  原    
	//结果是-1
	//a和b结果一样,都是有符号数

	
	unsigned char c = -1;

	//char类型8个比特位最多可以放11111111,进行整形提升
	//这里有个重点是无符号数整形提升的时候高位直接补0
	//00000000000000000000000011111111
	//因为是无符号数,无符号数的原反补码都一样,所以这就是原码。

	//打印出来结果是255

	printf("a=%d,b=%d,c=%d", a, b, c);
}

5. char类型下%u的打印

(%u是一个无符号整数的打印)

int main()
{
	char a = -128;
	//10000000000000000000000010000000  原
	//11111111111111111111111101111111  反
	//11111111111111111111111110000000  补
   
	//char类型发生截断
	//10000000

	//%u打印无符号整数
	//进行整形提升(这里看的是char a是有符号数,有符号数整形提升补符号位)
	//             (注意看的不是打印出来的%u,无符号整数就补0哦)
	// 看类型是不是有符号数,是的话补符号位,10000000,这里1是符号位
	//如果是无符号数的话,直接补0

	//11111111111111111111111110000000   补码 
	//打印的是无符号数,原反补一样直接打印、
	//结果是4,294,967,168

	printf("%u\n", a);

	return 0;
}

6.浮点型在内存中的存储

浮点型家族有浮点数家族包括: float、double、long double 类型。

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:   

                   (-1)^S * M * 2^E

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

M表示有效数字,大于等于1,小于2,写成科学计数法

2^E表示指数位。

 e可以为负数,m要写成科学计数法,小数点向左做移动几个单位,乘以几次方,向右移动几个单位,乘以负几次方

看下面两个例子

 以int存储,*pfloat打印时 。    先写出二进制,写出E M S然后还原回来。

(如果E里面都是0的话,用1-127,E里面不全为1或者0时,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

(M还原的时候省了小数点前面的值1或0,只还原小数点后面的值)

(S就是符号位)

 

以*pfloat存储,int打印时,要转化成浮点型的存储

先写成二进制1001.0 ,然后利用公式进行转化,求出S M E,再求出二进制,求二进制的时候下面正好反过来

(E里面不全为1或者0时,即指数E的计算值加去127(或1023),得到真实值,再将有效数字M前减上第一位的1)

(M还原的时候省了小数点前面的值1或0,只还原小数点后面的值)

(S就是符号位)

130的二进制为10000010 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值