我需要明确转换malloc()的返回值吗?

55
我想询问以下情况:
char *temp;
temp = malloc(10);

由于malloc的返回类型是void*,所以在分配给temp之前,指向malloc返回的指针会被隐式转换为char*类型吗?标准在这方面有什么规定吗?

如果我们的指针变量是某个结构体类型:

struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));

如果我们为temp分配内存而不将其强制转换为struct node*类型,它是否会自动转换为struct node*类型,或者必须显式地将其转换为struct node*类型?


8
如果您需要使用C++编译器而不是C编译器编译代码,则需要进行强制类型转换。因此,尽管纯C语言不需要进行强制类型转换,但我大部分的代码都包含了显式的类型转换。我通常会使用/=C++=/标记来说明原因。 - Jonathan Leffler
虽然不是必需的,但对我来说有助于以后阅读代码时减少冗余。 - Xolve
2
请参见此问题 - unwind
4个回答

53
如果你喜欢“不要重复自己”的思想,那么你可能觉得在malloc()调用中不需要重复变量声明中的类型名称是很有吸引力的。因为正如大家指出的,除了函数指针外,指针可以在void *之间转换而不会丢失信息。
另外,关于这一点,你也不需要在使用sizeof时重复自己。你的第二个示例,在分配结构体时,可以像这样编写:
struct node *temp;
temp = malloc(sizeof *temp);

在我不那么自负的观点中,这是最好的方式。

避免重复自己可以减少你所写的内容量,从而降低任何其中错误出现的风险。

请注意sizeof参数中的星号,它表示“指向该指针所指对象的大小”,这当然与“类型struct node的大小”相同,但不需要重复类型名称。这是因为sizeof在编译时计算其参数表达式的大小。对于此示例,就像sizeof 3计算类型为int的表达式的大小一样,sizeof *temp计算类型为struct node的实例的大小。

当然,你确实要重复某些东西,即变量名称本身,但通常这是一个更简单的表达式,更容易正确书写,也更容易被编译器发现错误。


4
这是一个例子,应用DRY原则是一种不安全的编程实践(请参见下面的链接)。避免重复以减少错误的论点取决于上下文。当涉及到C语言中的指针时,由于其模糊性而臭名昭著,这将导致麻烦。我宁愿冗长并重复转换以在编译时发现问题(而不是运行时):https://www.securecoding.cert.org/confluence/display/seccode/MEM02-C.+Immediately+cast+the+result+of+a+memory+allocation+function+call+into+a+pointer+to+the+allocated+type - luis.espinal
3
通常情况下, securecoding.cert.org 的内容都是胡说八道。或者委婉地说,我在该网站上读到的每篇文章都充满了错误信息(比如 ftell vs fstat),被广泛认为是不好的和有害的编程风格,以及纯粹的盲目“安全”编程。 - R.. GitHub STOP HELPING ICE
2
@luis.espinal 嗯?类型转换可能会隐藏错误,因为它们明确告诉编译器“这样做!”,并且通常即使您要求的内容似乎不正确,也会防止它生成警告。每次您在 C 代码中看到一个转换时,都需要更加努力地考虑所需的情况以及为什么首先需要进行转换。如果没有必要,请勿进行转换。 - unwind
1
我个人不喜欢使用sizeof(temp)这种表示法。当表达式被用作参数时,sizeof的工作方式有点复杂(甚至可以使用未定义的函数而不会得到链接器错误)。在这里,它可能会让人感到困惑,因为通常情况下,运算符对于悬空或空指针是不好的。但在这里,它却神奇地起作用了。我认为只写sizeof(struct node)更清晰(特别是对于那些在你的代码中遇到困难的非经验程序员)。这只是我的个人意见。 - bartgol

34

C语言中的空指针可以被分配给任何没有显式类型转换的指针。


9
我认为这并不适用于函数指针。 - Bastien Léonard
12
C语言中并未定义是否可以将函数指针转换为非函数指针或反向转换。C++明确禁止这样做,并且C++1x在特定条件下支持这样做。 - Johannes Schaub - litb
11
POSIX(至少在2008年)要求函数指针与数据指针具有相同的大小,而C标准将其定义为未定义。 - Jonathan Leffler

11

C语言会自动从和向 void* 进行强制转换,因此转换将会自动完成。在C++中,只有向 void* 的转换会隐式发生,而对于另一个方向,需要显式转换。


3
请注意,C++支持将指针转换为void*类型而无需进行强制转换。 - anon

4
在C++中,您必须明确地进行强制转换,但这只是语言告诉您不要这样做的方式。
在C中,没有真正需要进行强制转换,因为内存就是内存-我将不得不搜索以查看最新的C标准是否需要它。

2
C99标准不需要强制转换。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接