C语言的类型系统-编码, 类型转换及其规范

来源:互联网 发布:乐山seo外包公司 编辑:程序博客网 时间:2024/06/04 23:36

C语言的类型系统

——————

 

汇编语言将存储器看成一个虚拟存储器,即将存储器看成一个大的字节数组,汇编语言并没有提供类型系统.  C语言将字节数组抽象成不同长度的字节数组.本文介绍C语言的类型系统以及类型之间相互转换的原则.

 

 

C语言的数据类型

————

 

C语言的类型是相当丰富的,它提供多种类型. C语言的数据类型具体有:

1.基本类型:整型(short/int/long/longlong (C99)),浮点型(float/double/long double(C99)),字符型(char-可以归整型),枚举型.

2.构造类型:数组,结构,联合.

3.指针类型.

4.空类型.

 

C标准明确规定char型占1个字节,其他数据类型的大小是Implementation-defined.但是现代处理器和编译器都采用ILP32LP64规范.见下表:

类型

ILP32规范(IA32)

ILP32对应的Intel数据类型

LP64(x86-64)

LP64对应的Intel数据类型

char

1

字节

1

字节

short

2

2

int

4

双字

4

双字

long

4

双字

8

四字

long long

8

-----

8

四字

指针

4

双字

8

四字

float

4

单精度

4

单精度

double

8

双精度

8

双精度

long double

10/12

扩展精度

10/16

扩展精度

本文是IA32,故采用ILP32规范进行分析.

 

 

计算机编码

————

 

现代计算机信息的表示,存储,传输都是都是通过二级制来完成的(具体的原因元芳懂得).通过二进制数字系统我们可以进行编码,诸如对整数,负数,浮点数近似值,字符等进行编码.

计算机的三种重要的数字表示:

1.无符号(unsigned)编码.---->对应C语言的无符号整数.

   假设一个整数数据类型有w.设位向量x=[xw-1, xw-1,,x0].定义一个函数B2Uw(Binary toUnsigned).

    B2Uw(x) =(i=0w-1)xi2i

2.补码(two's-complement)编码.---->对应C语言的整数.

   假设一个整数数据类型有w.设位向量x=[xw-1, xw-1,,x0].定义一个函数B2Tw(Binary toTwo's-complement).

    B2Tw(x) =-xw-12w-1+(i=0w-2)xi2i     (将最高有效位解释为负权)

3.浮点数(floating-point)编码.----->对应C语言的float/double/longdouble.

    C标准没有规定浮点数必须使用IEEE 754标准,但是现代计算机普通使用IEEE754.详见IEEE 754浮点数的表示(也可以参考csapp的第二章).

 

 

C语言的类型转换

————

 

C语言的类型转换分为隐式类型转换和强制类型转换

 

1.类型转换的原理.

(1).同类型的有符号和无符号数之间的转换(位模式的重新解释).

    典型案例: unsigned<->int

    

    有符号和无符号之间转换时候,位模式并没有变化.

 

(2).符号位扩展(保证值不变->可以使用数学归纳法证明).

   典型案例: short->int; unsigned short-> unsigned int

    

    C规范并没有要求符号位扩展,但是符号位扩展能够保证有符号的数值不变.所以大多数实现都是有符号扩展.

 

(3). 截断原理.

   典型案例: int->short; unsigned int->unsigned short

    

   有符号和无符号的截断都是高位截断.

 

(4).转换原理.

   典型案例: int->float/double; float->double

   了解了IEEE754浮点数标准,很容易理解int, float,double之间如何转换. int->float/double首先就是要规格化,然后舍入.再转换.

   a. int->float(32->32).显然,不会溢出,但是会舍入(精度损失).

    b. int/float->double.不会溢出,也不会舍入(不会有精度损失).

    c. double->float.值可能会溢出(+Infinity or -Infinity),可能会舍入.

    d. float/double->int.可能会溢出(C标准没有规范会溢出成什么结果. Intel兼容机通常是[10000]),0舍入. (+1.9->1,-1.9->-1).

 

2. C标准的规范.

(1).隐式类型转换(Implicit Conversion)[3]

   (a).Integer Promotion

   (b).Usual Arithmetic Conversion

   (c).由赋值产生的类型转换

 

(2).强制类型转换(Explicit Conversion or Type Cast)

 

3.编译器处理类型转换

例如:

src_t v;

dest_t*p;

*p =(dest_t)v;

假定: v放在%eax, p放在%edx.

 

src_t

dest_t

指令

类型

int

int

movl %eax, (%edx)

-

char

int

movsbl %al, (%edx)

符号位扩展

char

unsigned

movsbl %al, (%edx)

char->int->unsigned

unsigned char

int

movzbl %al, (%edx)

位扩展

int

char

movb %al, (%edx)

截断

unsigned

unsigned char

movb %al, (%edx)

截断

unsigned

int

movl %eax, (%edx)

位模式重新解释

 

reference:

1. 深入理解计算机系统(原书第2版)

2. Linux C编程一站式学习


(版权所有,转载时请注明作者和出处-dennis_fan-http://blog.csdn.net/dennis_fan )