我什么时候需要在C语言中转换malloc的结果?

时间:2015-02-11 16:50:58

标签: c malloc

基于this old question malloc返回指向void的指针

  

会自动安全地提升为任何其他指针类型

但是阅读K& R我发现以下代码

char *strdup(char *s)
{
char *p;
/* make a duplicate of s */
p = (char *) malloc(strlen(s)+1)

有什么区别?

3 个答案:

答案 0 :(得分:7)

对于符合C89或更高版本的任何实现,无需转换malloc()的结果。

Errata for The C Programming Language, Second Edition

中提到了投放malloc()的结果
  

142(§6.5,接近结尾):关于转换返回值的评论   malloc(“正确的方法是声明......然后明确地说   coerce“)需要重写。这个例子是正确的并且有效,但是   该建议在1988-1989 ANSI / ISO的背景下值得商榷   标准。没有必要(考虑到void *的强制   ALMOSTANYTYPE *是自动的),如果malloc或a,可能会有害   代理它,不能被声明为返回void *。明确的   演员可以掩盖意外的错误。另一方面,预ANSI,   演员是必要的,它也在C ++中。

(该链接不再有效。已故Dennis Ritchie的主页现在为here;它指向该书主页的updated location,但该链接也无效。)

最佳做法是将malloc()调用的结果直接分配给指针对象,并让void*的隐式转换处理类型一致性。 malloc()的声明需要通过#include <stdlib.h>显示。

(几乎可以想象您可能希望在需要显式转换的上下文中使用malloc()。我能想到的唯一情况是将malloc()的结果直接传递给可变参数函数需要一个除void*以外的指针类型的参数。在这种不寻常和假设的情况下,可以通过将结果赋值给指针对象并将该对象的值传递给函数来避免强制转换。)

转换malloc()结果的唯一好理由是(a)与C ++的兼容性(但需要编写编译为C和C ++的代码比你想象的更少),以及(b)与ANSI C之前的编译器的兼容性(但是需要满足这些编译器的需求很少并且变得越来越少)。

答案 1 :(得分:2)

首先:K&amp; R C很古老。

其次:我不知道该示例中是否包含完整代码,但在K&amp; R C中,如果没有另外声明,则假定函数具有int返回值。如果他没有声明malloc,则意味着就编译器而言它返回int,因此是演员。请注意,这是未定义的行为,即使在C89(最早的标准版本)和非常糟糕的做法;但他可能这样做是为了简洁,或者也许是因为懒惰 - 或者是出于其他一些历史原因;我不知道K&amp; R C的所有错综复杂,可能是void*char*演员阵容当时并不隐含。

我应该补充一点,这是一个非常严重的问题,因为intvoid*可能有不同的大小(并且经常这样做 - 最常见的例子是大多数x86_64代码,其中指针是64 -bit,但是ints是32位)。

更新: @KeithThompson告诉我代码来自第2版,malloc 在那里宣布。那个(不像第一版)仍然相关,如果非常过时的地方。

猜测该演员可能是为了与不合格的编译器兼容,这在当时很重要,因为许多[大多数?]编译器还没有完全符合。如今,你必须不遗余力地找到一个需要演员的人(不,C ++编译器不算数;他们是C ++编译器,而不是C编译器)。

答案 2 :(得分:1)

希望(或可能想要)交叉编译C和C ++的人经常投射malloc(.),因为C ++不会自动宣传void*

正如其他人在功能原型是可选的过去指出的那样,编译器会假设malloc()返回int,如果它没有看到具有潜在灾难性运行时结果的原型。

我试图在这个论点中看到一些观点,但我根本无法相信这种情况会以规律性发生,保证火葬的人随后可以投射malloc(.)

看看在这个网站上投出malloc(.)的任何问题并不重要,因为有人会愤怒地要求他们删除他们的演员,就像他们的眼睛流血一样。

NB:它没有任何好处,并且没有任何错误,因为它是混乱的malloc(.)。事实上,我所知道的唯一(真实)论点是,它引导人们去看演员而不是看论证 - 这才是最重要的!

我今天在这里看到了代码:

int** x=(int**)malloc(sizeof(int)*n);

很容易陷入虚假的安全感。 sizeof(int)正在做(或者在这种情况下没有做)工作,以确保从malloc(.)返回的内容是正确的。 (int**)无效。

我不是说投了它。我很平静。我当然认为,如果一个新手没有打电话给free(.)我们教他们之前那么我们会遇到关于施放malloc(.)的细微差别。