一、定义:
类型是对象占据内存空间的大小及存储方式,类型转换即是变换对象的内存空间大小和存储方式。
二、类型转换所造成的问题:
小转大一般没有什么问题,唯一的问题是造成了内存浪费,大转小问题就大了,可能会造成数据的精度丢失甚至截断,所以不管怎样都应该尽量避免类型转换,可是很多时候不是你想要避免就能避免的。
三、“大小”问题:
(1)基本的大小问题:
比如int和long,一个4B,一个8B,int是小类型,long是大类型,int转long是小转大,long转int是大转小,这个大小肉眼可见。
(2)那么如果是int和float呢?
这两个可都是4B啊,浮点数大于整数。
(3)那如果是int和unsigned int呢?
这两个也都是4B,按存储方式来看,unsigned更大,因而有符号转无符号是小转大,无符号转有符号是大转小。
四、自动类型转换
“无所谓,编译器会出手”。
(1)不同类型的数据运算:
有浮点数(不管是float还是double),所有对象统一转double;
没浮点数,有大则转大。
(2)不同类型的数据赋值:
右边的转成左边的。这个得视具体情况而定,有的时候有的编译器会报错,有的则进行转换。
五、强制类型转换
(1)定义:
自动类型转换由编译器做,C语言也允许程序员自己做类型转换,这便是强制类型转换。
(2)强制类型转换的语法:
(type_name) expression
例如:
int sum = 10;
int count = 3;
// 这里sum通过强制类型转换转成了double,count通过自动类型转换转成了double
double mean = (double) sum / count;
六、使用强制类型转换
对于一个优秀的程序而言,良好的编程习惯是:
使用强制类型转换,不要让编译器做自动类型转换。
这样做的好处在于一切尽在掌控之中。这让我想起了,上大学时老师曾经将到过,上世纪90年代的一次火箭发射事故的原因就在于一行未进行强制类型转换的代码引发的运算错误。
下面举一个例子感受一下:
计算某工厂目前可出厂的产品总件数用 total 表示,该工厂共有三个车间,已知:1 车间目前完成 10.9 件,2 车间目前完成 12.7 件,3 车间目前完成 11.8 件。
采用强制类型转换进行计算:
int total;
total=(int)10.9+(int)12.7+(int)11.8; // 33
采用自动类型转换进行计算:
int total=10.9+12.7+11.8; // 35
33和35显然差距明显,符合实际情况的是33。
七、最常见的类型转换场景:
在实际的应用之中,最常见的场景并不是数值类型间的类型转换,而是指针类型的转换,尤其是void*与具体类型指针间的转换:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
// 字符串是最普遍的情况
char* str;
/* 最初的内存分配 */
str = (char*)malloc(6);
memset((void*)str, 0, sizeof(str));
strcpy(str, "hello");
printf("String = %s, Address = %p\n", str, str);
/* 重新分配内存 */
str = (char*)realloc((void*)str, 12);
strcat(str, " world");
printf("String = %s, Address = %p\n", str, str);
free(str);
// 整数
int* i = (int*)malloc(4);
*i = 4;
printf("%d\n", *i);
free(i);
return(0);
}