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.但是现代处理器和编译器都采用ILP32或LP64规范.见下表:
类型 | 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=0…w-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=0…w-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
![](https://img-my.csdn.net/uploads/201211/20/1353398713_2150.jpg)
C规范并没有要求符号位扩展,但是符号位扩展能够保证有符号的数值不变.所以大多数实现都是有符号扩展.
(3). 截断原理.
典型案例: int->short; unsigned int->unsigned short
![](https://img-my.csdn.net/uploads/201211/20/1353398613_5092.jpg)
有符号和无符号的截断都是高位截断.
(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兼容机通常是[100…00]),向0舍入. (+1.9->1,-1.9->-1).
2. C标准的规范.
(1).隐式类型转换(Implicit Conversion)[3种]
(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:
(版权所有,转载时请注明作者和出处-dennis_fan-http://blog.csdn.net/dennis_fan )