为了账号安全,请及时绑定邮箱和手机立即绑定

我是否施放了malloc的结果?

我是否施放了malloc的结果?

达令说 2019-05-20 15:02:34
在这个问题,有人建议意见,我应该不会投的结果malloc,即int *sieve = malloc(sizeof(int) * length);而不是:int *sieve = (int *) malloc(sizeof(int) * length);为什么会这样呢?
查看完整描述

7 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

 ; 你没有投射结果,因为:

  • 这是不必要的,因为void *在这种情况下自动且安全地提升到任何其他指针类型。

  • 它增加了代码的混乱,转换不是很容易阅读(特别是如果指针类型很长)。

  • 它让你重复自己,这通常很糟糕。

  • 如果您忘记包含,它可以隐藏错误<stdlib.h>。这可能会导致崩溃(或更糟的是,导致崩溃,直到方式在后面的代码的一些完全不同的部分)。考虑如果指针和整数的大小不同会发生什么; 那么你通过强制转换隐藏了一个警告,可能会丢失你返回的地址。注意:从C11开始,隐式函数从C中消失,并且这一点不再相关,因为没有自动假设未声明的函数返回int

作为澄清,请注意我说“你不投”,而不是“你不需要投”。在我看来,即使你做对了也没有包括演员。这样做没有任何好处,但是一堆潜在的风险,包括演员表明你不知道风险。

还要注意,正如评论员指出的那样,上面谈的是直C,而不是C ++。我非常坚信C和C ++是不同的语言。

要进一步添加,您的代码会不必要地重复int可能导致错误的类型信息()。最好取消引用用于存储返回值的指针,将两者“锁定”在一起:

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

这也会移动length到前面以增加可见性,并删除多余的括号sizeof只有在参数是类型名称时才需要它们。许多人似乎不知道(或忽略)这一点,这使得他们的代码更加冗长。记住:sizeof不是功能!:)


虽然移动length到前面可能会增加在某些极少数情况下的可见性,但是在一般情况下,应该注意将表达式编写为:

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

因为sizeof在这种情况下保持第一个,所以确保乘法至少用size_t数学来完成。

比较:malloc(sizeof *sieve * length * width)malloc(length * width * sizeof *sieve)第二个可能溢出的length * width时间widthlength比较小的类型size_t


查看完整回答
反对 回复 2019-05-20
?
MMTTMM

TA贡献1869条经验 获得超4个赞

在C中,您不需要转换返回值malloc。返回的void指针malloc自动转换为正确的类型。但是,如果您希望使用C ++编译器编译代码,则需要进行强制转换。社区中的首选替代方案是使用以下内容:

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

如果你改变了类型,你还可以免去担心改变表达式的右侧sieve

人们已经指出,演员阵容很糟糕。特别是指针转换。


查看完整回答
反对 回复 2019-05-20
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

演员,因为:

  • 它使您的代码在C和C ++之间更具可移植性,并且正如SO经验所示,许多程序员声称他们在用C ++(或C加本地编译器扩展)编写时正在用C语言编写。

  • 如果不这样做可以隐藏错误:注意所有的混乱的SO例子,当写type *type **

  • 它让你不会注意到你没有找到#include合适的头文件的想法错过了森林的树木。这就像说“不要担心你没有要求编译器抱怨没有看到原型这一事实 - 那令人讨厌的stdlib.h是真正重要的事情要记住!”

  • 它强制进行额外的认知交叉检查。它将(声称的)所需类型放在您正在为该变量的原始大小进行的算术旁边。我敢打赌你可以做一个SO研究,它表明malloc()当有一个演员时,bug会被抓得更快。与断言一样,显示意图的注释可以减少错误。

  • 以机器可以检查的方式重复自己通常是一个主意。事实上,这就是一个断言,并且使用强制转换是一种断言。断言仍然是我们获得正确代码的最常用技术,因为图灵在很多年前提出了这个想法。


查看完整回答
反对 回复 2019-05-20
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

正如其他人所说,C不是必需的,而是C ++。如果您认为要使用C ++编译器编译C代码,出于某种原因,您可以使用宏,例如:

#ifdef __cplusplus# define NEW(type, count) ((type *)calloc(count, sizeof(type)))#else# define NEW(type, count) 
(calloc(count, sizeof(type)))#endif

这样你仍然可以以非常紧凑的方式编写它:

int *sieve = NEW(int, 1);

它将为C和C ++编译。


查看完整回答
反对 回复 2019-05-20
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

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


查看完整回答
反对 回复 2019-05-20
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

你没有强制转换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年的编译器呢?


查看完整回答
反对 回复 2019-05-20
  • 7 回答
  • 0 关注
  • 583 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信