C语言进阶笔记(深度剖析数据的存储)

文章目录

  • 本章重点
    • 1.数据类型详细介绍
        • 类型的基本归类
          • 整型家族
          • 浮点型家族
          • 结构类型
          • 指针类型
          • 空类型
    • 2.整形在内存中的存储:原码,反码,补码
    • 3.大小端字节序的介绍和判断
    • 4.浮点型在内存中的存储解析
      • 5.本章小练习

本章重点

1.数据类型详细介绍

数据类型分为:

char //字符型数据类型
int //整形
short //短整型
long //长整形
long long //更长的整形
float //单精度浮点型
double //双精度浮点型

他们在内存中所占的空间大小(大小决定了使用范围)
C语言进阶笔记(深度剖析数据的存储)_第1张图片

类型的基本归类

整型家族

char
unsigned char 无符号的字符类型
signed char 有符号的字符类型等同于 char
int
unsigned int
signed
short
unsigned short [int]
signed short [int]
long
unsigned long [int]
signed long [int]

浮点型家族

double
float

结构类型

数组类型
结构体类型 strcut
枚举类型 enum
联合体类型 union

指针类型

int *p1
char *p2
double *p3
float *p4
void * p5

空类型

void 表示为空类型
通常用于函数的返回值类型,函数的参数,指针类型

2.整形在内存中的存储:原码,反码,补码

在计算机中数据是以二进制的形式进行存储的
有符号的数有三种表示形式:原码,反码,补码。
补码=反码+1
对于正整数:原码,反码,补码,相同
对于整型:在内存中存储的是补码

3.大小端字节序的介绍和判断

C语言进阶笔记(深度剖析数据的存储)_第2张图片
C语言进阶笔记(深度剖析数据的存储)_第3张图片
我们先用补码看一看,他是多少?
6的原码,反码,补码相同都为
0000 0000 0000 0000 0000 0000 0000 0110
在内存存储是以十六进制进行存储的
00 00 00 06
-2的原码
1000 0000 0000 0000 0000 0000 0000 0010
反码
1111 1111 1111 1111 1111 1111 1111 1101
补码
1111 1111 1111 1111 1111 1111 1111 1110
以十六进制表示
FF FF FF Fe

为什么它是倒着存放的呢? 在这里我们就要讨论大小端问题啦
大端存储模式:是指数据的低位保存在内存中的高地址中,而数据的高地址保存在内存的低地址中
小端存储模式:是指数据的高位保存在内存中的高地址中,而数据的低地址保存在内存的低地址中

用图来分析更为直观
C语言进阶笔记(深度剖析数据的存储)_第4张图片
2015年百度面试题
请简述大端字节序和小端字节序的概念,设计一个小程序,判断你当前机器上的字节序

 #include 
int Judge(int n)
{
	char *m = (char*)n;
	if (*m == 1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
int main()
{
	int n = 1; 
	//00000000000000000000000000000001
	//char 截取 一个字节8个bit位 00000001
	//小端为 10 00 00 00
	//大端为 00 00 00 01
	int ret = Judge(n);
	if (ret == 1)
	{
		printf("小端字节序\n");
	}
	else
	{
		printf("大端字节序\n");
	}
	return 0;
}

在这里插入图片描述

4.浮点型在内存中的存储解析

引例:

#include 
 int main() 
{ 
 int n = 9; 
 float *pFloat = (float *)&n; 
 printf("n的值为:%d\n",n); 
 printf("*pFloat的值为:%f\n",*pFloat); 
 *pFloat = 9.0; 
 printf("num的值为:%d\n",n); 
 printf("*pFloat的值为:%f\n",*pFloat); 
 return 0; 
} 

在我们没有学习,浮点型数据在内存中的存储式,我妄自揣测一下大家应该是这样想的把
int n 的地址被强制类型转化成 float
第一个输出为 9
第二个输出为 9.000000
第三个输出为 9
第四个输出为 9.000000
但是输出却不是这样,这是为什么呢?

C语言进阶笔记(深度剖析数据的存储)_第5张图片
那就进入正题喽
浮点型在内存中的存储 和 整形存储有这不一样的地方
在这里

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位

举例来说:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。 那么,按照上面V的格式,可以得出s=0,
M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2
C语言进阶笔记(深度剖析数据的存储)_第6张图片
IEEE 754对有效数字M和指数E,还有一些特别规定。 前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形
式,其中xxxxxx表示小数部分。为了能够存储更多的位数,略去1

至于指数E,情况就比较复杂。 首先,E为一个无符号整数(unsigned int)这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的 取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E
是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001


5.0的存储
101.0
1.01x2^2
M=1.01
E=2
S=2
0 00000010 01000000000000000000000

然后,指数E从内存中取出还可以再分成三种情况:
1.E不全为0或不全为1
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

在这里计算 0.5
0.5 转化成为二进制形式 为 0.1,因为M部分必须为1.……,所以讲M向前移意为变成(1.0)*2^(-1)
所以E = -1+127=126
M=23个0
S = 0
所以二进制形式为 0 01111110 00000000000000000000000

2.E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为
0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

3.E全为1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

5.本章小练习

计算输出的结果是什么
1.

 #include 
int main()
{
	char a = -1;
	//sign char 和 char 都是一个意思
	signed char b = -1;

	

unsigned char c = -1;
	//10000001
	//11111110
	//11111111 无符号数
	//%d 输出 整型提升  无符号的整形提升,各位补零
	//00000000 00000000 00000000 11111111 原,反,补,相同
	printf("a=%d,b=%d,c=%d", a, b, c);
	return 0;
}

在这里插入图片描述
2.

 #include  
 int main()
 {
	char a = -128;
	//char 的范围是-128 到 127
	//要打印一个无符号数
	//原码  10000000 00000000 00000000 10000000 
	//反码  11111111 11111111 11111111 01111111
	//补码  11111111 11111111 11111111 10000000
	//char 类型 截取                   10000000
	//整形提升                         最高位为1,认为符号位
	// 	    11111111 11111111 11111111 10000000
	//      此处打印为,无符号整数 打印 所以认为 11111111 11111111 11111111 10000000全部为有效位
	//                                                                               4294967168

	printf("%u\n", a);
	return 0;
 }
 

在这里插入图片描述
3. `

 #include  
int main()
{
	char a = 128;
	//00000000 00000000 00000000 10000000 原,反,补,相同
	//char 类型                  1 0000000 1为符号位
	//整形提升 11111111 11111111 11111111 10000000
	// 4294967168
	printf("%u\n", a);
	return 0;
}

在这里插入图片描述
4.

 #include 
int main()
{
    int i = -20;
	unsigned int j = 10;
	// -20
	//10000000 00000000 00000000 00010100  原码
	//11111111 11111111 11111111 11101011  反码
	//11111111 11111111 11111111 11101100  补码
    //10
	//00000000 00000000 00000000 00001010  原码 原 ,反,补 相同
	//  -20+10
	//11111111 11111111 11111111 11110110  补码
	//11111111 11111111 11111111 11110101  反码
	//10000000 00000000 00000000 00001010  原码
	//-10
	printf("%d\n", i + j);
	return 0;
}

在这里插入图片描述
5.

#include 
 int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	//因为i是无符号数,所以他被无论怎么减,都会大于0
	//所以死循环
	return 0;
}

在打印中也可以看到,unsigned int 的值的范围:0到429467295
C语言进阶笔记(深度剖析数据的存储)_第7张图片
6 .

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

在这里插入图片描述

解析:
C语言进阶笔记(深度剖析数据的存储)_第8张图片
7.

 #include  
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	//死循环打印hello world 
	//因为unsigned char 的范围 为0~255,所以无论如何,都在0~255 255+1就进入下一个循环,从0开始
	return 0;
}

C语言进阶笔记(深度剖析数据的存储)_第9张图片

你可能感兴趣的:(c语言,c语言)