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

When do I need to cast the result of malloc in C language?

本问题已经有最佳答案,请猛点这里访问。

基于这个老问题,malloc返回一个指向void的指针,

is automatically and safely promoted to any other pointer type

但在阅读K&R时,我发现了以下代码

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

有什么区别?


对于任何符合C89或更高版本的实施,不需要强制执行malloc()的结果。

c编程语言勘误表第二版中提到了malloc()的转换结果:

142(§6.5, toward the end): The remark about casting the return value
of malloc ("the proper method is to declare ... then explicitly
coerce") needs to be rewritten. The example is correct and works, but
the advice is debatable in the context of the 1988-1989 ANSI/ISO
standards. It's not necessary (given that coercion of void * to
ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a
proxy for it, fails to be declared as returning void *. The explicit
cast can cover up an unintended error. On the other hand, pre-ANSI,
the cast was necessary, and it is in C++ also.

(该链接不再有效。已故的丹尼斯·里奇的主页现在在这里;它指向书主页的更新位置,但链接也无效。)

最佳实践是将malloc()调用的结果直接分配给指针对象,并让来自void*的隐式转换处理类型一致性。malloc()的声明需要通过#include 可见。

(很难想象您可能会在需要显式转换的环境中使用malloc()。我能想到的唯一情况是将malloc()的结果直接传递给一个变量函数,该函数需要一个指针类型的参数,而不是void*。在这种异常和人为的情况下,可以通过将结果赋给指针对象并将该对象的值传递给函数来避免强制转换。)

EDOCX1的8个结果的唯一好的原因是(a)与C++的兼容性(但是需要编写编译为C和AS C++的代码比您期望的更高),和(b)与ANSI C编译器之间的兼容性(但是满足这些编译器的需要是罕见的并且变得越来越稀少)。


首先:K&R C很古老。

其次:我不知道这是否是该示例中的完整代码,但在K&R C中,如果没有另外声明,则假定函数具有int返回值。如果他不声明malloc,就编译器而言,这意味着它返回int,因此是强制转换。请注意,即使在C89(最早的标准化版本)中,这也是未定义的行为,而且实践极为糟糕;但他这样做可能是为了简洁,或者可能是因为懒惰,或者是出于其他历史原因;我不知道K&R C的所有错综复杂之处,也可能是void*char*类型的类型不是IMP。那就舔回去。

我应该补充一点,这是一个非常严重的问题,因为intvoid*可能有不同的大小(而且通常是这样——最常见的例子是大多数x86 code,其中指针是64位,但int是32位)。

更新:@keitththompson已经通知我代码来自第二版,并且在那里声明了malloc。这一点(与第一版不同)仍然相关,如果在某些地方非常过时。

我猜演员阵容可能是为了与不符合标准的编译器兼容而进行的,而这在当时最重要的是(最多的是)?]编译器还没有完全符合要求。现在,你必须想办法找到一个需要强制转换的编译器(而不是,C++编译器不算数;它们是C++编译器,而不是C编译器)。


想要(或可能需要)交叉编译C和C++的人经常会抛出EDOCX1 0,因为C++不会自动地促进EDCOX1 1。

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

我试图从这一论点中看到一些观点,但我简直无法相信这种情况会有规律地发生,这就要求燃烧的人们必须把埃多克斯一号(0号)扔出去。

看看在这个网站上铸造malloc(.)的任何问题,不管是关于什么,有些人会愤怒地要求他们移除他们的铸造,好像他们会让他们的眼睛流血一样。

注:这对我们没有好处,也没有错,所以我们把malloc(.)放在杂乱的地方。事实上,我所知道的唯一(真实)的论点是,它引导人们去看演员,而不是去看论点——这才是最重要的!

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

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

很容易让人产生一种虚假的安全感。sizeof(int)正在做(或在这种情况下没有做)工作,以确保从malloc(.)返回的内容是正确的。(int**)不起作用。

我不是说"施展它"。我在呼吁冷静。我当然认为,如果一个新手没能打电话给free(.),我们会在进入到malloc(.)的细微差别之前给他们上一课。