C语言支持基础类型的互相转换,包括自动类型转换和强制类型转换。
对于基础类型的转换,如果未声明转换类型,会自动进行自动类型转换。而如果声明了转换类型,则会进行强制类型转换。例如char类型可以直接赋值给int类型,这就是自动类型转换。自动类型转换方便快捷,但是其隐藏的机制十分复杂,稍不注意就会导致数据精度降低、高位丢失等问题,在编写代码时需要特别注意。
自动类型转换
对于自动类型转换,主要发生在表达式中,例如算术表达式(+,-,*,/,%),赋值表达式(=)中,下面分别进行说什么。
运算表达式中的类型转换
算术表达式一般是一个或者多个变量进行算术运算,在大部分情况下,都会使用相同的数据类型进行运算,不过在某些情况下,也会发生不同数据类型的运算。
具体示例如下所示。
#include
int main(int argc, char *argv[])
{
int a = 10;
short b = 20;
// short类型向int类型转换
int c = a + b;
float f1 = 1.0f;
// int类型向float类型转换
float f2 = a + f1;
unsigned char d = 10;
// unsigned char类型向int类型转换
int e = a + d;
printf("%d, %d, %d\n", a, b, c);
printf("%f, %f\n", f1, f2);
printf("%d, %d\n", d, e);
return 0;
}
对于上述代码,具体执行结果如下所示。

在上述语句中,a和b都是int类型,但因为f1是float类型,最终a+f1的结果也是float类型。这里面就涉及到类型的优先级,主要规则如下所示。
这里还有一个隐藏的知识点,如果浮点数声明末尾不带f,会默认存储为double类型,只有带f才会
对于运算表达式中的类型转换,默认情况下都是低级别类型向高级别类型转换,例如int向float转换,long向double转换等。占用空间更大,被称为类型升级,大部分情况下不关注也不会出现问题。
赋值表达式和函数传参中的类型转换
赋值表达式和函数传参中的类型转换则与运算不同,主要是将基本数据类型变量赋值给其它类型变量,具体示例如下所示。
#include
void func(unsigned char val)
{
if (val > 100) {
printf("over 100, val:%d\n", val);
} else {
printf("below 100, val:%d\n", val); // below 100, val:99
}
}
int main(int argc, char *argv[])
{
// 浮点型赋值给int类型
int v1 = 355.5;
// int类型赋值给unsigned char类型
unsigned char v2 = v1;
long long v3 = v1;
printf("v1 = %d\n", v1); // v1 = 355
printf("v2 = %d\n", v2); // v2 = 99
printf("v3 = %lld\n", v3); // v3 = 355
// 将int类型传递到unsiged char类型
func(v2);
return 0;
}
对于上述代码,具体执行结果如下所示。

可以看到,在赋值表达式中,既可以把低级别类型赋值给高级别类型(int赋值给long long类型), 也可以把高级别类型赋值给低级别类型(如float赋值给int类型,int赋值给unsigned char类型)。
对于类型升级,其值仍然保持不变,只是类型被提升。而类型降级时,对于float转int类型,则会丢弃小数部分,只保留整数部分。而int转unsigned char类型时,如果int值大于unsigned char类型的最大值,会发生截断,只保留低8位,这就直接造成了值的变化;这种操作都是自动的,很可能在不知晓的情况发生。
函数的参数作为后续执行的判断条件,那么自动类型转换后,直接改变了参数值,执行了非预期的代码,这在某些情况下会造成严重的结果,因此需要特别注意。

1316

被折叠的 条评论
为什么被折叠?



