我是否施放了malloc的结果?

这个问题,有人建议意见,我应该不会投的结果malloc,即

int *sieve = malloc(sizeof(int) * length);

而不是:

int *sieve = (int *) malloc(sizeof(int) * length);

为什么会这样呢?


达令说
浏览 591回答 7
7回答

呼唤远方

无&nbsp;;&nbsp;你没有投射结果,因为:这是不必要的,因为void *在这种情况下自动且安全地提升到任何其他指针类型。它增加了代码的混乱,转换不是很容易阅读(特别是如果指针类型很长)。它让你重复自己,这通常很糟糕。如果您忘记包含,它可以隐藏错误<stdlib.h>。这可能会导致崩溃(或更糟的是,不导致崩溃,直到方式在后面的代码的一些完全不同的部分)。考虑如果指针和整数的大小不同会发生什么;&nbsp;那么你通过强制转换隐藏了一个警告,可能会丢失你返回的地址。注意:从C11开始,隐式函数从C中消失,并且这一点不再相关,因为没有自动假设未声明的函数返回int。作为澄清,请注意我说“你不投”,而不是“你不需要投”。在我看来,即使你做对了也没有包括演员。这样做没有任何好处,但是一堆潜在的风险,包括演员表明你不知道风险。还要注意,正如评论员指出的那样,上面谈的是直C,而不是C ++。我非常坚信C和C ++是不同的语言。要进一步添加,您的代码会不必要地重复int可能导致错误的类型信息()。最好取消引用用于存储返回值的指针,将两者“锁定”在一起:int&nbsp;*sieve&nbsp;=&nbsp;malloc(length&nbsp;*&nbsp;sizeof&nbsp;*sieve);这也会移动length到前面以增加可见性,并删除多余的括号sizeof;&nbsp;只有在参数是类型名称时才需要它们。许多人似乎不知道(或忽略)这一点,这使得他们的代码更加冗长。记住:sizeof不是功能!:)虽然移动length到前面可能会增加在某些极少数情况下的可见性,但是在一般情况下,应该注意将表达式编写为:int&nbsp;*sieve&nbsp;=&nbsp;malloc(sizeof&nbsp;*sieve&nbsp;*&nbsp;length);因为sizeof在这种情况下保持第一个,所以确保乘法至少用size_t数学来完成。比较:malloc(sizeof *sieve * length * width)与malloc(length * width * sizeof *sieve)第二个可能溢出的length * width时间width和length比较小的类型size_t。

MMTTMM

在C中,您不需要转换返回值malloc。返回的void指针malloc自动转换为正确的类型。但是,如果您希望使用C ++编译器编译代码,则需要进行强制转换。社区中的首选替代方案是使用以下内容:int&nbsp;*sieve&nbsp;=&nbsp;malloc(sizeof&nbsp;*sieve&nbsp;*&nbsp;length);如果你改变了类型,你还可以免去担心改变表达式的右侧sieve。人们已经指出,演员阵容很糟糕。特别是指针转换。

牛魔王的故事

你做演员,因为:它使您的代码在C和C ++之间更具可移植性,并且正如SO经验所示,许多程序员声称他们在用C ++(或C加本地编译器扩展)编写时正在用C语言编写。如果不这样做可以隐藏错误:注意所有的混乱的SO例子,当写type *对type **。它让你不会注意到你没有找到#include合适的头文件的想法错过了森林的树木。这就像说“不要担心你没有要求编译器抱怨没有看到原型这一事实 - 那令人讨厌的stdlib.h是真正重要的事情要记住!”它强制进行额外的认知交叉检查。它将(声称的)所需类型放在您正在为该变量的原始大小进行的算术旁边。我敢打赌你可以做一个SO研究,它表明malloc()当有一个演员时,bug会被抓得更快。与断言一样,显示意图的注释可以减少错误。以机器可以检查的方式重复自己通常是一个好主意。事实上,这就是一个断言,并且使用强制转换是一种断言。断言仍然是我们获得正确代码的最常用技术,因为图灵在很多年前提出了这个想法。

呼啦一阵风

正如其他人所说,C不是必需的,而是C ++。如果您认为要使用C ++编译器编译C代码,出于某种原因,您可以使用宏,例如:#ifdef&nbsp;__cplusplus#&nbsp;define&nbsp;NEW(type,&nbsp;count)&nbsp;((type&nbsp;*)calloc(count,&nbsp;sizeof(type)))#else#&nbsp;define&nbsp;NEW(type,&nbsp;count)&nbsp; (calloc(count,&nbsp;sizeof(type)))#endif这样你仍然可以以非常紧凑的方式编写它:int&nbsp;*sieve&nbsp;=&nbsp;NEW(int,&nbsp;1);它将为C和C ++编译。

蝴蝶刀刀

在C中,您可以隐式地将void指针转换为任何其他类型的指针,因此不需要强制转换。使用一个人可能会向不经意的观察者建议,有一些理由需要一个,这可能会产生误导。

收到一只叮咚

你没有强制转换malloc的结果,因为这样做会给你的代码带来无意义的混乱。人们投射malloc结果的最常见原因是因为他们不确定C语言是如何工作的。这是一个警告信号:如果您不知道特定语言机制的工作原理,那么请不要猜测。查找或询问Stack Overflow。一些评论:可以将void指针转换为/从任何其他指针类型转换而不进行显式转换(C11 6.3.2.3和6.5.16.1)。但是,C ++不允许在void*另一个指针类型之间进行隐式转换。所以在C ++中,演员阵容是正确的。但是如果你用C ++编程,你应该使用new而不是malloc()。而且你永远不应该使用C ++编译器编译C代码。如果需要使用相同的源代码同时支持C和C ++,请使用编译器开关来标记差异。不要尝试使用相同的代码来区分两种语言标准,因为它们不兼容。如果C编译器由于忘记包含头而无法找到函数,那么您将收到编译器/链接器错误。因此,如果您忘记包含<stdlib.h>那些没什么大不了的话,那么您将无法构建您的程序。对于遵循超过25年的标准版本的古代编译器,忘记包含<stdlib.h>将导致危险的行为。因为在那个古老的标准中,没有可见原型的函数隐式地将返回类型转换为int。然后显式地从malloc转换结果将隐藏此错误。但这确实不是问题。您没有使用25年的计算机,那么为什么要使用25年的编译器呢?
打开App,查看更多内容
随时随地看视频慕课网APP