C 语言中的类型转换
我们在前面学习了 C 语言的数据类型,那么变量在参与运算的时候类型是始终如一不变的吗?
带着这个疑问,我们可以先看一个例子:
#include <stdio.h>
#define typename(x) \_Generic((x), /\* Get the name of a type \*/ \
\
\_Bool: "\_Bool", unsigned char: "unsigned char", \
char: "char", signed char: "signed char", \
short int: "short int", unsigned short int: "unsigned short int", \
int: "int", unsigned int: "unsigned int", \
long int: "long int", unsigned long int: "unsigned long int", \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
float: "float", double: "double", \
long double: "long double", char \*: "pointer to char", \
void \*: "pointer to void", int \*: "pointer to int", \
default: "other")
int main()
{
int a=1,b=2;
float c=3.14159,d=0;
printf("a type: %s, b type: %s, c type: %s, d type: %s\n",typename(a),typename(b),typename(c),typename(d));
a=b+c;
printf("a=b+c, a=%d\n",a);
printf("type (b+c): %s\n",typename(b+c));
d=b+c;
printf("d=b+c, d=%f\n",d);
return 0;
}
经过编译运行后得到如下的结果:
Tips:有关如何编译运行的内容请参考前面的章节。
Tips:同时值得注意的是,这个程序中的 _Generic 来自于 C11 标准中,所以在你之前可能看到的 C 语言的书籍中是没有的。请大家不要使用过于古老的编译器,请使用推荐的较新的编译器。也就是支持 C11 以上标准的编译器。具体情况可以参照你们所选择的编译器的手册。或者直接选择 GCC 7 及更新版本的编译器。
a type: int, b type: int, c type: float, d type: float
a=b+c, a=5
type (b+c): float
d=b+c, d=5.141590
这里面的 a, b 变量为整形,而 c 和 d 都是浮点型。那么当一个整形和一个浮点型相加的时候会发生什么呢?这就是我们今天要介绍的内容。
1. 隐式类型转换
C 语言是强类型语言,也就是说不同类型的数据之间是不能进行运算的。必须保持一致的类型才能进行运算。也就是说在这个不同数据类型的计算过程中,C 语言自动进行了一次类型转换,使得两个变量的数据类型一致,才能进行相关的计算。这种自动的转换,也称之为隐式类型转换。
从前面提及的例子还可以看出,我们定义的数据类型,在不同的类型的数据运算结束后,并没有发生改变,也就是数据类型保持着我们最开始定义时候的类型。这时会发生丢弃精度的事情,也就是上面例子中小数点后面的数值就会消失。
那么这种隐式的转换有什么规律可循吗?
下面的表格就展示了类型转换的规律,当在计算过程中,数值类型不一致的时候,就会发生自动的类型转换,转换的类型是将表格中处于下方的较低优先级的数据类型,向表格上方的较高优先级的数据类型进行转换。
级别 | 数据类型 |
---|---|
1 | long double |
2 | double |
3 | float |
4 | unsigned long long |
5 | long long |
6 | unsigned long |
7 | long |
8 | unsigned int |
9 | int |
10 | char short int |
根据这个表格我们就可以看出之前的转换中,int 与 float 类型进行计算,编译器会自动将 int 类型转换为 float 类型进行计算。从而使得运算在相同的数据类型间进行。
2. 显式类型转换
如果说隐式类型转换是编译器自动进行的类型转换,那么显式类型转换,则是我们人为的进行数据类型的转换,这里可以理解为是一种强制的类型的转换,这种转换将不再遵守上面的转换规则,而是按照我们人为的标明的类型进行转换。
就是在我们需要指定类型的变量前加上数据类型,并用圆括号包裹。例如: (int)a, (float)b, (long)c 等。
下面我们通过一个示例程序来看一下显式类型转换: