协慌网

登录 贡献 社区

我是否施放了 malloc 的结果?

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

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

而不是:

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

为什么会这样呢?

答案

没有投出结果,因为:

  • 这是不必要的,因为在这种情况下, 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)widthlength小于size_t时,第二个可能会溢出length * width

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

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

如果您改变sieve的类型,这使您不必担心改变表达式的右侧。

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

演员,因为:

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