数据存储(六)


数据存储(六)

C语言内置类型

char //字符类型
short //短整型类型
int //整型类型
long //长整型类型
float //单精度浮点类型
double //双精度浮点类型
类型的意义

  1. 决定数据在内存中所占的字节数
  2. 数据在内存中的存储方式

类型的基本归类

整型类型

char
char在内存中存储的是ASCII码,ASCII码是整数,所以char是整型

unsigned char
signed char

short

unsigned short [int]
signed short [int]

int

unsigned int
signed int

long

unsigned long [int]
signed long [int]

浮点类型

float,double

构造类型

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

指针类型

int* pi
char* pc
float* pf
void* pv

空类型

void表示空类型(无类型)
通常用与函数返回类型,函数的参数,指针类型

整型在内存中的存储

只要是整数,内存中存储的都是二进制的补码
正数
原码 反码 补码相同
负数
原码(直接列出该数的二进 制) -> 反码(符号位不变,其他位按位取反) -> 补码(反码+1)

大端小端存储模式

大端存储模式,别名大端字节序存储模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中
小端存储模式,别名小端字节序存储模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//判断当前机器是大端还是小端
#include <stdio.h>
int sys()
{
int a=1;
return *(char*)&a;
//指针类型决定了指针解引用操作能访问几个字节,char*访问一个字节
}
int main()
{
if(sys()==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}

整型提升

C的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为“整型提升”。

例题

例1

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main()
{
char a=-1;
//11111111
signed char b=-1;
//11111111
unsigned char c=-1;
//11111111
printf("a=%d,b=%d,c=%d\n",a,b,c);
return 0;
}
//a=-1,b=-1,c=255

例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
char a=-128;
//原:10000000000000000000000010000000
//反:11111111111111111111111101111111
//补:11111111111111111111111110000000
//a为10000000
//%u为无符号整型数
//a整型提升后11111111111111111111111110000000
printf("%u\n",a);//4294967168

return 0;
}

例3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
int main()
{
int i=-20;
//原:100000000000000000000000000010100
//反:111111111111111111111111111101011
//补:111111111111111111111111111101100
unsigned int j=10;
//000000000000000000000000000001010
//i+j为
//111111111111111111111111111110110
//%d有符号整数,所以将i+j的值格式化为有符号整数
//补:111111111111111111111111111110110
//反:111111111111111111111111111110101
//原:100000000000000000000000000001010
printf("%d\n",i+j);//-10
return 0;
}

浮点数在内存中的存储

根据国际标准IEEE 754(IEEE二进位浮点数算术标准),任意一个二进制浮点数V可以表示成下面形式:

(-1)^SM2^E
(-1)^S表示符号位,当S为0,V为正数,当S为1,V为负数
M表有效数字,范围1<=M<2
2^E表指数位

举例:

9.0
1001.0
(-1)^S * M * 2^E
(-1)^0 * 1.001 * 2^3

IEEE 754规定
对于32位的浮点数,最高1位是符号位S,接着8位是E,剩下23位为有效数字M
对于64位的浮点数,最高1位是符号位S,接着11位是E,剩下52位为有效数字M
IEEE754
有效数字M
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx分。比如保存1.01的时候,只保存01 ,等到读取的时候,再把第一位的1加上去。
指数E
E为一个无符号整数这意味着,如果E为8位,它的取值范围为0-255;
如果E为11位,它的取值范围为0-2047
但科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;
对于11位的E,这个中间数是1023,比如,2^-1的E是-1,所以保存成32位浮点数时,必须保存成-1+127=126,即01111110。
例:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
float f=5.5;
//5.5
//101.1
//(-1)^0*1.011*2^2
//S=0,M=1.011,E=2
//0 10000001 01100000000000000000000
return 0;
}

指数E从内存中取出还可以在分成三种情况:
E不全为0或不全为1:即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
E全为0:浮点数的指数E等于-126(或者-1022)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx小数。这样做是为了表示±0,以及接近于0的很小的数字。
E全为0:表示±无穷大(正负取决于符号位s)。
例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
int main()
{
int n=9;
//00000000000000000000000000001001
float* p=(float*)&n;
printf("n的值为:%d\n",n);//9
//0 00000000 00000000000000000001001
//(-1)^0*0.00000000000000000001001*2^-126
printf("*p的值为:%f\n",*p);//0.000000
*p=9.0;
//1001.0
//(-1)^0*1.001*2^3
//0 10000010 00100000000000000000000
//1091567616
printf("n的值为:%d\n",n);//1091567616
printf("*p的值为:%f\n",*p);//9.000000
return 0;
}
/*结果为
n的值为:9
*p的值为:0.000000
n的值为:1091567616
*p的值为:9.000000
*/

Author: ljs
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source ljs !
评论
  TOC