当前位置:文档之家› 数据类型转换

数据类型转换

数据类型转换各类整数之间的转换C语言中的数分8位、16位和32位三种。

属于8 位数的有:带符号字符char,无符号字符unsigned char 。

属于16位数的有:带符号整数int,无符号整数unsigned int(或简写为unsigned),近指针。

属于32位数的有:带符号长整数long,无符号长整数 unsigned long,远指针。

IBM PC是16位机,基本运算是16位的运算,所以,当8位数和16位数进行比较或其它运算时,都是首先把8 位数转换成16位数。

为了便于按2的补码法则进行运算,有符号8位数在转换为16位时是在左边添加8个符号位,无符号8位数则是在左边添加8个0。

当由16位转换成8位时,无论什么情况一律只是简单地裁取低8位,抛掉高8 位。

没有char或usigned char常数。

字符常数,像"C",是转换为int以后存储的。

当字符转换为其它 16 位数(如近指针)时,是首先把字符转换为int,然后再进行转换。

16位数与32位数之间的转换也遵守同样的规则。

注意,Turbo C中的输入/输出函数对其参数中的int和unsignedint不加区分。

例如,在printf函数中如果格式说明是%d 则对这两种类型的参数一律按2 的补码(即按有符号数)进行解释,然后以十进制形式输出。

如果格式说明是%u、%o、%x、%X,则对这两种类型的参数一律按二进制 (即按无符号数) 进行解释,然后以相应形式输出。

在scanf函数中,仅当输入的字符串中含有负号时,才按2的补码对输入数进行解释。

还应注意,对于常数,如果不加L,则Turbo C一般按int型处理。

例如,语句printf("%081x",-1L),则会输出ffffffff。

如果省略1,则输出常数的低字,即ffff。

如果省略L,则仍会去找1个双字,这个双字的就是int常数-1,高字内容是不确定的,输出效果将是在4个乱七八糟的字符之后再跟ffff。

在Turbo C的头文件value.h中,相应于3 个带符号数的最大值,定义了3个符号常数: #define MAXSHORT 0X7FFF#define MAXINT 0X7FFF#define MAXLONG 0X7FFFFFFFL 在Turbo C Tools中,包括3对宏,分别把8位拆成高4位和低4位,把16位拆成高8位和低8位,把32位拆成高16位和低16位。

uthinyb(char value) utlonyb(char value)uthibyte(int value) utlobyte(int value)uthiword(long value) utloword(long valueu)在Turbo C Tools中,也包括相反的3 个宏,它们把两个4位组成一个8位,把两个8位组成一个16位,把两个16位组成一个32位。

utnybbyt(HiNyb,LoNyb) utwdlong(HiWord,Loword)utbyword(HiByte,LoByte)实数与整数之间的转换Turbo C中提供了两种实数:float和 double。

float 由32 位组成,由高到低依次是:1个尾数符号位,8个偏码表示的指数位(偏值=127),23个尾数位。

double由64位组成,由高到低依次是:1 个尾数符号位,11个偏码表示的指数位(偏值=1023), 52个尾数位。

通过下列公式,可以由尾数和指数计算出所代表的实数值: X=±1.尾数*2(指数-偏值) 下列几种情况下,此公式不成立:指数=000...0且尾数 =00...0,则X=X=±0指数=000...0且尾数!=00...0,则X=±0.尾数*2(1-偏值)指数=11....1且尾数 =00...0,则X=±∞指数=11....1且尾数!=00...0,则X是一个无效数在Turbo C的头文件value.h中,相应于实数所能达到的最大最小值,定义了如下几个符号常数: #define MAXFLOAT 3.37E+38#define MINFLOAT 8.43E-37#define MAXDOUBLE 1.797693E+308#define MINDOUBLE 2.225074E-308 实常数是按double格式存放的,如果想按float 格式存放,则必须加后缀F,如:1.23E+4F。

当把实数强制转换为整数时,采取的是“向零靠拢的算法",如: float值: 65432.6 -65432.6 转换为long; 65432 -65432转换为unsigned: 65432 104如果不希望“向零靠拢”,而希望“四舍五入”,则必须由程序员自己处理。

一种办法是先加上(符号位/2),然后再进行类型转换。

应该注意的是:如果被转换的实数值超过了目标类型的表达范围,则会产生错误。

例如上面的float值-65432,6转换为unsigned int值时,由于超过了目标范围,所产生的104就是错误的。

在65432。

6转换为unsigned int的65432以后,可以用printf的%u格式输出,如果用 %d格式输出,则会得到错误的结果。

指针说明指针是包含另一变量的地址变量。

它的一般说明形式,如int *fd,其fd是一个指向整型变量的指针。

比较复杂的指针说明,如*(*pfpi)(),可按如下几个原则来理解:以标识符为中心,一对方括号一般表示数组,一对圆括号一般表示函数或强调某一优先顺序,方括号对和圆括号对为同一优先级,方括号和圆括号比*号优先级高。

以下几例解释了这些原则的应用。

int *fip(),因圆括号优先级高,帮fip 先与圆括号结合,说明fip是一个函数,这个函数返回一个指向整数的指针。

int (*pfi)(),因两对圆括号为同一优先级,故从左到右,pfi是一个指针,这个指针指向一个函数,这个函数返回一个整数。

int *par[],因方括号比*号优先级高,故par是一个数组,这个数组的每一个元素是指向整数的指针。

int (*ptr)[],因方括号与圆括号为同一优先级,故ptr 是一个指针,这个指针指向一个数,这个数的每一个元素是一个整数。

int *(*pfpi)(),pfpi是一指针,这个指针指向一个函数,这个函数返回一个提向整数的指针。

指针与地址指针在使用之前必须初始化,给指针赋地址的方法一般有如下几种:第一种很容易理解,通过取地址操作符取变量(包括结构变量)的地址,如:char_c="a", *ptr_char;ptr_char=&c; 第二种是数组,因为不带方括号的数组名等效于数组中第一个元素的地址,即数组名也可看作是一个指针,所以有两种办法。

如: char myname[31], *ptr; ptr=myname;或 ptr=&myname[0];第三种是动态分配的一块内存,这时往往带有类型强制转换,但应注意当内存不够时,可能返回一个空(NULL)指针。

如: struect complex {double real, image; };struct complex *ptr;ptr={ struct complex *)malloc(sizeof(struct complex)); 第四种是函数,与数组名一样,函数名也可以当作一个地址,于是可以把函数名赋给一个指向函数的指针。

函数名后面跟一个带圆括号的参数表意味着计算函数的值,但仅有一个函数名则意味着指向函数的指针。

如:double (*fx)();double quad_poly(double);fx=quad_poly;指针运算常见的指针运算有:指针加或减一个数,指针增量,指针减量,指针比较等等。

假设P是某数组第1个元素的指针,则P+N 就是这个数组中第n 个元素的地址,每个元素占多少存储单元则由指针所指数组的类型来确定。

但有两点要注意:第一,上面这段话是C语言对指针运算的普遍规律,但具体到种C编译则有所不同,尤其是在80X86类型的机器上。

Turbo C和Microsoft C 6.0以前的版本把指针分为near、far、huge,Microsoft C 6.0又增加了based。

在这几种指针中,只有huge严格遵守上面的指针运算规则,详见下一节。

第二,当指针应用于数组尤其是多维数组时,有时容易弄错,下表说明了数组法与指针法的区别。

│ 1维│ 2维│ 3维━━━━━━━━━━┿━━━━━┿━━━━━━━┿━━━━━━━━━━数组说明│int x[] │int y[][] │int z[][][]指针说明│int *xptr │int *yptr[] │int *zptr[][]数组法表示某元素地址│&x[i] │&y[i][j] │&z[i][j][k]指针法表示某元素地址│ptr+i │*(yptr+i)+j │*(*(zptr+i)+j)+k数组法存取某元素│x[i] │y[i][j] │z[i][j][k]指针法存取某元素│*(ptr+i) │*(*(yptr+i)+j)│*(*(*(zptr+i)+j)+k)指针分类在C 语言教科书上,指针就是指针,不存在分类的问题。

我们经常说“指向整数的指针”,“指向结构的指针”,“指向函数的指针”等等,只是说指针指向不同的目标,而不是说指针本身有什么区别。

但是,在以80X86为基础的微机上实现C 语言时,由于80X86的物理地址空间不是线性连续的而是分段的,为了提高效率,就必须对指针加以分类。

各类指针的运算法则也不一样。

Turbo C 2.0及以前的版本,Microsoft C 6.0以前的版本,指针都是分类三类,近(near),远(far),巨(huge)。

Microsoft C 6.0版本中,出现了一种新的指外类型,这就是基(based)指针。

基指针综合实现了近和远指针的优点,它像近指针那么小那么快,又像远指针那样可以寻址缺省数据段以外的目标。

基指针这个名字就反映了这类指针上的实现方法:它是以程序员指定的某一地址为段基址。

如果在C 源程序中使用了基指针,编译程序一般先把所指定的段基址装在ES寄存器内。

在缺省的数据段内,程序员一般不会使用基指针。

但若同时要使用多个数据段,基指则有其明显的优点。

一、近(near)指针近指针是用于不超过64K 字节的单个数据段或码段。

对于数据指针,在微、小和中编译模式下产生的数据指针是近指针,因为此时只有一个不超过64K 字节的数据段。

对于码(即函数指针)指针,在微、小和紧凑编译模式下产生的码指针是近指针,因为此时只一个不超过64K字节的码段。

相关主题