计算机进行算术运算时,通常要求操作数具有相同的位数、相同的存储方式。而C语言支持在表达式中混合使用基本数据类型,因此需要在不同的数据类型之间进行转换。在C语言中存在两种类型的转换,一种是隐式转换,由编译器自动处理转换而无需程序开发人员介入,另一种是强制类型转换(显式转换),需要程序开发人员使用强制转换运算符显式地表明转换。
隐式转换
隐式转换主要发生在以下情况:
- 当算术表达式或逻辑表达式中操作数的类型不一样时
- 任一操作数为浮点数时,将占用字节较少的类型的操作数转换为占用字节较多的类型的操作数(称为提升)。
- 两个操作数都非浮点数时,若操作数中有字符型或短整型,先将该操作数进行整型,再将占用字节较少的类型提升。有符号操作数和无符号操作数作为两个操作数参与算术运算时,会通过将符号位当成数字位的方法将有符号数转换为无符号数,可能导致程序错误。
- 当赋值运算符右侧表达式的类型和左侧变量的类型不同时,总把赋值表达式右边的表达式值转换为左边变量类型的值。
- 当函数调用时使用的实际参数和形式参数类型不同时
- 当return语句中表达式的类型和函数声明的返回值类型不一致时。
强制类型转换
C语言中提供了强制类型转换,显式地对进行类型转换,其表达式格式为:
(类型名) 表达式
类型名为表达式的值应该转换的类型。C语言将强制转换中的(类型名)
看作是一元运算符,其优先级高于二元运算符。
/**************************************
* conversion.c *
* *
* C语言中的类型转换 *
**************************************/
#include <stdio.h>
int main()
{
char c = 'A';
short int s = 0;
int i = 0;
unsigned int u = 0;
long int l = 0;
unsigned long int ul = 0;
float f = 0.0f;
double d = 0.0;
long double ld = 0.0;
/*隐式转换*/
i = i + c; /*c转换为int*/
i = i + s; /*s转换为int*/
u = u + i; /*i转换为unsigned int*/
l = l + u; /*u转换为long int*/
ul = ul + l;/*l转换为unsigned long*/
f = f + ul; /*ul转换为float*/
d = d + f; /*f转换为double*/
ld = ld + d;/*d转换为long double*/
/*强制类型转换*/
long int li = 0;
int j = 1000;
li = (unsigned long)j * j;
printf("li = %lu\n", li);
return 0;
}
typedef
类型定义
除了用宏来定义类型外,可以利用类型定义来定义新的类型,其格式为:
typedef 原类型名 新类型名;
与宏不同的是,编译器会把将新类型名作为一个类型名加入到类型列表中,而不是再预处理过程中被替换。
类型定义可以有力支持程序的可移植性。C语言自身就用typedef为那些可能因C语言的不同实现而不同的类型定义类型名,这些类型名以_t
结尾,例如size_t
, wchar_t
等。
sizeof
运算符
sizeof
运算符用于计算指定类型值所需空间的大小,其格式为:
sizeof(类型名)
返回值为无符号整型,说明存储类型名的值需要的字节数。sizeof
除了用以类型名,也可以用以常量、变量和表达式。sizeof
是一元运算符,优先级高于二元运算符。
由于sizeof
表达式的类型由实现定义,在显式sizeof
值时建议将其转换为unsigned long
型,使用转换声明"%lu"
。
/****************************************
* using_sizeof_typedef.c *
* *
* C语言中的sizeof运算符及typedef *
****************************************/
#include <stdio.h>
int main()
{
typedef int Integer;
printf("Integer占%lu个字节\n", (unsigned long)sizeof(Integer));
Integer a = 0;
printf("a占%lu个字节\n", (unsigned long)sizeof(a));
return 0;
}
参考文献
- K.N. King 著,吕秀峰 译. C语言程序设计-现代方法. 人民邮电出版社