在这个问题上,有人在评论中建议我不要使用malloc的结果。即,我应该这样做:
int *sieve = malloc(sizeof(*sieve) * length);
而不是:
int *sieve = (int *) malloc(sizeof(*sieve) * length);
为什么会这样?
在这个问题上,有人在评论中建议我不要使用malloc的结果。即,我应该这样做:
int *sieve = malloc(sizeof(*sieve) * length);
而不是:
int *sieve = (int *) malloc(sizeof(*sieve) * length);
为什么会这样?
当前回答
在C语言中,可以隐式将void指针转换为任何其他类型的指针,因此不需要强制转换。使用一个可能会向不经意的观察者暗示需要一个的原因,这可能会误导人。
其他回答
在C语言中,可以将空指针分配给任何指针,这就是为什么不应该使用类型转换的原因。如果您想要“类型安全”分配,我可以推荐以下宏函数,这些函数我总是在C项目中使用:
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)
有了这些,你可以简单地说
NEW_ARRAY(sieve, length);
对于非动态数组,第三个必须的函数宏是
#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
这使得阵列环路更加安全和方便:
int i, a[100];
for (i = 0; i < LEN(a); i++) {
...
}
尽可能在C语言中编程时最好做的事情是:
通过C编译器编译程序,并打开所有警告-Wall并修复所有错误和警告确保没有声明为auto的变量然后使用带有-Wall和-std=C++11的C++编译器对其进行编译。修复所有错误和警告。现在再次使用C编译器进行编译。您的程序现在应该在没有任何警告的情况下编译,并且包含更少的错误。
这个过程使您可以利用C++严格的类型检查,从而减少错误的数量。特别是,此过程强制您包含stdlib.否则您将得到
malloc未在此范围内声明
并且还强制你使用malloc的结果,否则你会得到
从void*到T的转换无效*
或者你的目标类型是什么。
用C而不是C++编写的唯一好处是
C具有明确规定的ABIC++可能会生成更多代码[异常、RTTI、模板、运行时多态性]
请注意,在理想情况下,当使用C所共有的子集和静态多态特性时,第二个缺点应该消失。
对于那些觉得C++严格规则不方便的人,我们可以使用带有推断类型的C++11特性
auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...
对我来说,这里的结论是,在C语言中使用malloc是完全没有必要的,但是如果你使用了C语言,它不会影响malloc,因为malloc仍然会为你分配你请求的内存空间。另一个原因是人们进行选角的原因或原因之一,这是为了使他们能够用C或C++编译相同的程序。
可能还有其他原因,但几乎可以肯定的是,其他原因迟早会让你陷入严重的麻烦。
来自维基百科:
铸造的优点包括强制转换可以允许C程序或函数编译为C++。强制转换允许最初返回char*的1989年以前版本的malloc。如果目标指针类型发生变化,强制转换可以帮助开发人员识别类型大小的不一致,特别是如果指针声明的位置远离malloc()调用(尽管现代编译器和静态分析器可以在不需要强制转换的情况下警告此类行为)。铸造的缺点根据ANSI C标准,铸件是多余的。添加强制转换可能会掩盖将标头stdlib.h包含在找到了malloc的原型。如果没有malloc的原型,标准要求C编译器假设malloc返回一个int。如果没有强制转换,则警告为当该整数被分配给指针时发出;然而,随着演员,这个警告没有产生,隐藏了一个bug。在某些情况下体系结构和数据模型(例如64位系统上的LP64,其中long和指针为64位,int为32位),此错误可能实际上导致未定义的行为,正如隐式声明的malloc返回32位值,而实际定义的函数返回64位值。取决于调用约定和内存布局,这可能会导致堆栈损坏。这个问题不太可能在现代编译器中不被注意,因为它们统一地生成警告已使用未声明的函数,因此警告将仍然出现。例如,GCC的默认行为是显示警告:“内置的不兼容隐式声明函数”,而不管是否存在强制转换。如果指针的类型在其声明时发生了更改,则可以此外,需要更改调用和强制转换malloc的所有行。
尽管malloc不带强制转换是首选方法,大多数有经验的程序员都会选择它,但在意识到问题后,您应该使用任何您喜欢的方法。
即:如果您需要将C程序编译为C++(尽管它是一种单独的语言),则必须强制转换使用malloc的结果。
正如其他人所说的,它不是C所必需的,而是C++所必需的。如果您认为要使用C++编译器编译C代码,无论出于何种原因,都可以使用宏,例如:
#ifdef __cplusplus
# define MALLOC(type) ((type *)malloc(sizeof(type)))
# define CALLOC(count, type) ((type *)calloc(count, sizeof(type)))
#else
# define MALLOC(type) (malloc(sizeof(type)))
# define CALLOC(count, type) (calloc(count, sizeof(type)))
#endif
# define FREE(pointer) free(pointer)
这样,您仍然可以以非常紧凑的方式编写它:
int *sieve = MALLOC(int); // allocate single int => compare to stack int sieve = ???;
int *sieve_arr = CALLOC(4, int); // allocate 4 times size of int => compare to stack (int sieve_arr[4] = {0, 0, 0, 0};
// do something with the ptr or the value
FREE(sieve);
FREE(sieve_arr);
它将为C和C++编译。