0xAA55 发表于 2017-1-5 06:08:56

【C】经典问题:我用malloc分配内存给数组的时候,是不是应该把返回值转换成对应的类型?

标题有点长,我换句话描述一下就是:

int *array = (int*)malloc(50 * sizeof *array);
int *array = malloc(50 * sizeof *array);
这两句是上面好还是下面好?

VS党一般都会说,肯定是上面好,而GCC党则认为下面好。

首先我先说明一下,这两条语句到底有啥区别:
第二句不能在C++里编译通过,它是C语言的语句,因为C语言的void*可以转换成任何类型,C++则不支持这样的转换。
因此对于C语言而言,这种转换是多余的。
第一句有个强制类型转换,也就是说无论malloc的返回类型是什么,它都会试图将其转换为int*。
这里重点说一下,为什么要注意这个。

1、malloc是C标准库的函数,理论上是跨平台的,但不是所有的平台都在stdlib.h里面声明了它的原型。
你可以说“我用malloc.h”,这是个好主意,多数平台都有这个头文件,而且它里面一定会有malloc函数的声明。
有的平台没有在stdlib.h里声明malloc函数,这会导致malloc被临时定义为一个返回int类型的函数。
一旦malloc的返回值类型是int,而你的代码被编译到了64位的环境,如果你没有强制类型转换,编译器就会认为这个函数返回的不是int,而是一个指针。而如果你写了强制类型转换,编译器就会认为“你是故意把一个32位返回值赋值给64位指针变量的”,于是,它就在没有任何提示的情况下,把malloc的返回值的低32位部分赋值给了你的变量,隐藏了一个BUG(估计很多开发者在遇到崩溃、找这个BUG的时候都得吐血!)

2、这种情况很少在VS党身上发生,因为VS的智能提示功能是针对C++的,就算你写的是用C编译器编译的、后缀是.c的彻彻底底的C语言文件,VS也会用C++的智能提示在你的代码上画上难看的红色波浪线,提示你“无法将void*类型转换为int*类型”,即使你能成功编译它,即使编译器本身并不会给你任何警告。
但要知道开发者们有谁没有强迫症呢,于是VS党们都会老老实实地进行强制类型转换(然后在写跨平台x64的时候经历一次挫折,哈哈哈哈哈哈哈)
关键是,VS的malloc.h和stdlib.h里都有malloc的声明,并且都是返回void*的。不跨平台的话,万事大吉,这是不是也说明VS阻碍了跨平台开发呢?

总结一下,在跨平台开发的时候,你如果能保证你的源码里一定会有正确的malloc函数的声明,或者,你希望你的代码能够通过C++的编译,那么,请用强制类型转换。否则,直接把malloc的返回值不经过任何转换传递给你的指针变量,才是明智之举,即使VS强行给你打上丑陋的波浪线!
页: [1]
查看完整版本: 【C】经典问题:我用malloc分配内存给数组的时候,是不是应该把返回值转换成对应的类型?