在这个问题上,有人在评论中建议我不要使用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语言中,可以将空指针分配给任何指针,这就是为什么不应该使用类型转换的原因。如果您想要“类型安全”分配,我可以推荐以下宏函数,这些函数我总是在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中使用malloc,则无需键入cast,因为它会自动键入cast。然而,如果您使用的是C++,那么应该键入cast,因为malloc将返回void*类型。
在C语言中,您得到了从void*到任何其他(数据)指针的隐式转换。
习惯于GCC和Clang的人被宠坏了。外面不是很好。
这些年来,我被要求使用的过时的编译器吓坏了。公司和管理者通常采用极端保守的方法来更改编译器,甚至不会测试新的编译器(具有更好的标准遵从性和代码优化)是否能在他们的系统中工作。对于正在工作的开发人员来说,实际情况是,当你在编写代码时,你需要覆盖你的基础,不幸的是,如果你不能控制什么编译器可以应用于你的代码,那么使用mallocs是一个好习惯。
我还建议许多组织应用自己的编码标准,如果定义了编码标准,那么这应该是人们遵循的方法。在缺乏明确指导的情况下,我倾向于选择最有可能在任何地方编译,而不是盲目地遵守某个标准。
根据现行标准,这是不必要的,这一论点是非常有效的。但这一论点忽略了现实世界的现实性。在一个完全由当今标准统治的世界里,我们并没有编码,而是由我喜欢称之为“地方管理的现实领域”的实用性来控制。这比太空时代更加弯曲和扭曲
YMMV。
我倾向于将使用malloc作为防御操作。不漂亮,不完美,但总体安全。(老实说,如果你没有包含stdlib.h,那么你会遇到比强制执行malloc更多的问题!)。
我更喜欢演演员,但不是手动。我最喜欢使用glib中的g_new和g_new0宏。如果不使用glib,我会添加类似的宏。这些宏在不损害类型安全的情况下减少代码重复。如果类型错误,将在非空指针之间进行隐式转换,这将导致警告(C++中的错误)。如果忘记包含定义g_new和g_new0的标头,则会出现错误。gnew和gnew0都采用相同的参数,不像malloc采用比calloc更少的参数。只需添加0即可获得零初始化内存。该代码可以用C++编译器编译而无需更改。
TL;博士
int *sieve = (int *) malloc(sizeof(int) * length);
有两个问题。类型转换,并且您使用类型而不是变量作为sizeof的参数。相反,请这样做:
int *sieve = malloc(sizeof *sieve * length);
长版本
不您不必计算结果,因为:
这是不必要的,因为在这种情况下,void*会自动安全地升级为任何其他指针类型。它给代码增加了混乱,强制转换不太容易阅读(特别是如果指针类型很长)。这会让你重复自己,这通常是不好的。如果您忘记包含<stdlib.h>,它可能会隐藏错误。这可能会导致崩溃(或者更糟糕的是,直到稍后在代码的某个完全不同的部分发生崩溃)。考虑如果指针和整数的大小不同会发生什么;然后你通过投射来隐藏警告,可能会丢失返回地址的一部分。注意:从C99开始,隐式函数从C中消失,这一点不再相关,因为没有自动假设未声明的函数返回int。
作为澄清,请注意我说的是“你不需要投”,而不是“你不必投”。在我看来,这是一个失败的演员阵容,即使你做得对。这样做根本没有好处,但有一系列潜在的风险,包括演员阵容表明你不知道这些风险。
另外,正如评论家指出的,上面提到的是直接C,而不是C++。我非常坚信C和C++是独立的语言。
此外,代码不必要地重复类型信息(int),这可能会导致错误。最好取消引用用于存储返回值的指针,将两者“锁定”在一起:
int *sieve = malloc(length * sizeof *sieve);
这还将长度移到前面以增加可见性,并删除sizeof的多余括号;只有当参数是类型名时,才需要它们。许多人似乎不知道(或忽略)这一点,这使得他们的代码更加冗长。记住:sizeof不是函数!:)
虽然在一些罕见的情况下,将长度移到前面可能会增加可见性,但也应注意,在一般情况下,最好将表达式写成:
int *sieve = malloc(sizeof *sieve * length);
在这种情况下,由于首先保持sizeof,确保乘法至少使用size_t数学运算完成。
比较:malloc(sizeof*sive*length*width)与malloc,当width和length的类型小于size_t时,第二个可能会溢出长度*宽度。