Should I explicitly cast malloc()'s return value?
我想问一下以下情况:
1 2
| char *temp ;
temp = malloc(10); |
由于malloc的返回类型是void*类型,那么malloc返回的指针在被分配到temp之前是否会隐式转换为char*类型?标准在这方面说了什么?
如果指针变量是某种结构类型,例如:
1 2
| struct node *temp ;
temp = (struct node *)malloc(sizeof(struct node )); |
如果我们将内存分配给temp而不将其强制转换为struct node*类型,那么它是隐式强制转换为struct node*类型,还是需要显式强制转换为struct node*类型?
- 如果您可能需要用C++编译器代替C编译器编译代码,则需要强制转换。因此,我的大多数代码都包含显式强制转换——即使纯C不需要它。我通常用/*= C++**来标记它。
- 虽然不是必需的,但对我来说,以后可以帮助我阅读代码,而不会太冗长。
- 另请参见此问题。
如果您喜欢"不要重复自己"的心态,那么您不需要在malloc()调用中重复变量声明中的类型名,这应该是很有吸引力的。因为,正如人们所指出的,您不会:指针转换为void *或从void *转换而不丢失,函数指针除外。
另外,在这一点上,你也不需要重复使用sizeof。第二个示例,在分配结构时,可以这样编写:
1 2
| struct node *temp ;
temp = malloc(sizeof *temp ); |
在我看来,这是最好的办法。
避免重复会减少你写的东西的数量,这反过来又降低了那些东西出错的风险。
注意sizeof参数中的星号,这意味着"该指针指向的对象的大小",这当然与"struct node类型的大小"相同,但不重复类型名。这是因为sizeof计算(编译时!)作为其参数的表达式的大小。对于这种情况。就像sizeof 3计算int类型表达式的大小一样,sizeof *temp计算struct node实例的大小。
当然,您确实需要重复一些操作,例如变量名本身,但这通常是一个更简单的表达式,并且更容易纠正,而且编译器也更容易在其中发现错误。
- 这是一个应用dry是不安全编程实践的例子(请参见下面的链接)。避免重复减少错误的论据是上下文相关的。当涉及到c中的指针时,由于歧义而臭名昭著,它将导致糟糕的juju。我更愿意详细地重复这些转换,以便在编译时发现问题(而不是运行时):securecodeing.cert.org/confluence/display/seccode/…
- 像往常一样,securecodeing.cert.org充满了垃圾。或者,更客气地说,我在那个网站上读到的每一篇文章都充满了不正确的信息(想想ftell和fstat),被广泛认为是不好的和有害的风格,和/或仅仅是普通货物崇拜的"安全"编程。
- @路易斯·埃斯皮纳尔?强制转换可以隐藏错误,因为它们明确地对编译器说"执行此操作!"并且通常会阻止它生成警告,即使您所要求的似乎是错误的。每当您看到一个CAST C代码时,如果需要什么,您需要更仔细地考虑,以及为什么一开始就认为CAST是必要的。如果你不需要的话,就不要铸造。
- 我个人不喜欢sizeof(*temp)符号。当表达式用作参数时,sizeof的工作方式有点复杂(甚至可以使用未定义的函数,并且不会出现链接器错误)。这里可能会混淆,因为*运算符在悬空指针或空指针上通常很糟糕。在这里它神奇地工作。我认为仅仅编写sizeof(结构节点)就更清楚了(特别是对于那些不熟悉代码的程序员来说)。只有我个人的意见。
C中的空指针可以分配给任何指针,而无需显式转换。
- 我认为它不适用于函数指针。
- c不定义是否可以将函数指针强制转换为非函数指针或返回。C++明确禁止它,C++ 1x有条件地支持它。
- 而posix(至少2008年)要求函数指针与数据指针大小相同,因为C标准没有定义。
c隐式从void*向void*强制转换,因此强制转换将自动完成。在C++中,只对void*进行转换,隐式地进行,对于另一个方向,需要显式强制转换。
在C++中,必须显式地强制转换,但这实际上是语言使你放弃它。在C语言中,实际上不需要强制转换,内存只是内存——我必须搜索一下,看看最新的C标准是否需要它。