C语言:类型存储

类型存储

char: 可能为signed char unsigned char ,根据编译器不同实现不同。占位一个字节。Signed char取值范围为-128~127unsigned char 取值范围为0~255

举例:A: 65 内存中的位模式:

0

1

0

0

0

0

1

0

short: 通常占位2字节。默认为signed short, 取值范围-215~215-1。另有unsigned short,取值范围0~216-1

举例:1027:内存中的位模式(本文一律采用大端存储的方式):

0

0

0

0

0

1

0

0

0

0

0

0

0

0

1

1

-1027:位模式:

1

1

1

1

1

0

1

1

1

1

1

1

1

1

0

1

计算机采用补码来存储整数。补码的表示方法如下:

正数:与原码相同;

负数:对其绝对值原码按位取反,然后加1

用补码存储整数主要有以下几个好处:

  1. 计算加减法时,可以将符号域统一处理,简化电路设计。以-1027+1027为例,在计算机中存储计算过程为:1111101111111101 + 0000010000000011 = 10000000000000000,高位1舍去,等于0
  2. 补码在变换一个数的正负属性时,其过程是相同的,不需要额外的电路设计。依然以1027为例: 对0000010000000011按位取反然后加1,得到1111101111111101,即-1027。现在对-1027,即1111101111111101按拉取反然后加1,又得到0000010000000011,即1027
  3. 正零和负零在补码中的表示是相同的。

int: 通常占位24个字节。现代编译器多为4字节,故现以4字节为准。默认为 signed int,取值范围-231~231-1。另unsigned int,取值范围0~232-1

举例:65539

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

1

1

-65539

1

1

1

1

1

1

1

1

1

1

1

1

1

1

1

0

1

1

1

1

1

1

1

1

1

1

1

1

1

1

0

1

long: 通常占位48字节。占位4字节时与int相同,占位8字节时与long long相同。略。

long long: 通常占位8字节。默认signed long long,取值-263~263-1。另unsigned long long,取值0~264-1。举例略。

注:c99中仅要求:sizeof(short) <= sizeof(int) <= sizeof(long) < sizeof(long long),对各类型占字节数并无明确规定,与各编译器的实现有关。

float: 占位4字节,其内存中位模式布局如下:

S

Exponent

Mantissa

其中,最高位(第31位)S为符号位,取值0(正数),1(负数)。

后面的八位(第30~23位),为指数位,取值0~255

最后的二十三位(第22~0位),为尾数位,分别代表2-12-2……2-23

Float代表的数值f = (-1)S * (1+Mantissa) * 2(exponent - 127),所以理论上浮点数可表示的取值范围为-(2 - 2-23)*2128 ~ (2 - 2-23)*2128。但是还有几种特殊情况需要处理,所以计算机在存储浮点数时有以下规定:

  1. 当指数部分为0且尾数部分为0时,该数为正负0(取决于符号位)
  2. 当指数部分为255且尾数部分为0时,该数为正负无穷大。(取决于符号位)
  3. 当指数部分为255且尾数部分不为0时,该数非法(NaN)。

所以实际上浮点数可表示的取值范围为-(2 - 2-23)*2127 ~ (2 - 2-23)*2127

举例:19.375:先将19.375的整数部分与小数部分分别二进制化,得到10011.011,然后将其通过移位变换到1~2-2-31范围内:1.0011011 * 24,于是得到其在内存中的位模式:

0

1

0

0

0

0

0

1

1

0

0

1

1

0

1

1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

又如:-0.625:其二进制表示为-0.101,移位得:-1.01 * 2-1,于是得其在内存中的位模式:

1

0

1

1

1

1

1

1

0

0

1

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

但是有些小数是无法在有限的位数内将其二进制化的,以0.9为例,对其二进制化将得到一个无限循环的二进制小数:0.1110011001100……,可我们存储小数部分的只有二十三位,于是只能将后面的部分截断,这就产生了浮点数的精度问题。这也是为什么不能对浮点数用==符号判断相等的原因:计算机是按位比较来判断两数是否相等的,但0.90.3 + 0.6的内存位模式布局却可能是不一样的。

0.9内存布局:

0

0

1

1

1

1

1

1

0

1

1

0

0

1

1

0

0

1

1

0

0

1

1

0

0

1

1

0

0

1

1

0

a = 0.3; b = 0.6; c = a + b; c的内布局为:

0

0

1

1

1

1

1

1

0

1

1

0

0

1

1

0

0

1

1

0

0

1

1

0

0

1

1

0

0

1

1

1

float的精度由其尾数决定,因223 = 8388608,共七位,故float的精度为小数点后6~7位有效数字。

double: 占位8字节。其存储原理与float相同,不过将指数部分扩展到11位,将尾数部分扩展到52位。其取值范围为:-(2 - 2-52) * 21023~(2 - 2-52) * 21023。其精度为小数点后15~16位有效数字。举例略。

Pointer通常定义为 unsigned long类型。占位48字节。

数组:在内存中连续存储同一类型的数据。

举例: char letters[] = {‘A’, ‘B’, ‘C’, ‘D’};letters 内存布局:

A

B

C

D

struct: 在内存中连续存储多种(不同类型)数据。

举例:struct {int a, char b[4], short c[2]}st; st内存布局:

int

char

char

char

char

short

short

union: 在内存中存储多种(不同类型)数据,这些数据共用同一块内存,同一时间只能访问其中某一种数据。

举例:union{int a, short b, char c}un; un内存布局:

|---------------------------------------------- int -----------------------------------------------|

|---------------------short--------------------|

|----------char--------|

猜你喜欢

转载自www.cnblogs.com/lc19890709/p/9320574.html