为什么C ++需要为malloc()进行强制转换,但C不需要?

时间:2010-08-13 14:22:07

标签: c++ c malloc

我一直对此感到好奇 - 为什么在C ++中我必须从malloc投射返回值而不是在C中?

以下是C ++中的示例:

int *int_ptr = (int *)malloc(sizeof(int*));

这是C ++中不起作用的示例(没有强制转换):

int *int_ptr = malloc(sizeof(int*));

我听说在C中,事实上,从malloc()转换输出是一个错误。

有人可以评论这个话题吗?

4 个答案:

答案 0 :(得分:32)

有几点:

C允许将void指针隐式转换为任何其他对象指针类型。 C ++没有。

如果您忘记包含stdlib.h或者在范围内没有malloc()声明,那么在C中转换malloc()的结果将会产生有用的诊断。请记住,如果C看到没有事先声明的函数调用,它将假定函数返回int。如果你没有malloc()的声明并且你离开了演员阵容,那么你将得到一个诊断,你正试图分配不兼容的类型(int到指针)。如果你强制转换结果,你就会产生运行时问题,因为不能保证将指针值转换为int并再次返回指针会给你一个有用的结果。

如果您正在编写C ++,那么您应该使用newdelete而不是malloc()free()。是的,是的,是的,我已经听说过人们希望他们的代码编译成C和C ++的所有原因,但是使用正确的内存管理工具为语言带来的好处超过了维护两个版本IMO的成本。

注意:C89标准中添加了void *类型;早期版本的C有malloc()返回char *,因此在这些版本中,如果您将结果分配给不同的指针类型,则需要 。几乎每个人都支持至少C89标准,所以你遇到其中一个较旧的实现的可能性非常非常低。

答案 1 :(得分:13)

那是因为C ++是一种强类型语言。在C ++中,只有在“扩展”时才允许隐式强制转换,也就是说,如果新类型可以包含旧类型可以容纳的每个值。允许从较小的整数类型转换为较大的整数类型;允许从任何指针类型转换为void*;允许从子类转换为其超类。所有其他演员必须明确制作,从而告诉编译器“我知道我在做什么,这不是一个错误”。

malloc()返回void*,这可能是任何东西,因此编译器无法保证您的演员表能够成功(或有意义)。通过使用显式强制转换,您告诉编译器您正在做的事情实际上是有意的。

C,OTOH,没有这种严格的铸造规则;你可以愉快地在任何两种类型之间进行投射,而你作为程序员负责确保不会发生任何不良事件。

答案 2 :(得分:9)

C支持从void*到其他指针类型的隐式转换。 C ++不允许它。

在C中明确强制转换malloc的返回值的一个原因是,如果malloc签名未包含在当前编译单元中,编译器将假定返回类型是int并将其隐式转换为您指定的指针类型,导致您立即解决的编译时警告。如果你犯了这个错误,就不会发出警告。

答案 3 :(得分:1)

C的类型规则非常宽松,而C ++的规则更为严格。在这种情况下的区别是C允许在对象指针和void指针之间进行隐式转换/分配。 C ++没有。

实际上,作为旧式通用C编程的一部分,旧式C甚至鼓励了与void指针的隐式转换。 C ++从来不需要void指针,因为它具有函数重载和模板等功能。在C ++中使用void指针通常很麻烦。

关于在不包含malloc的情况下就强制转换stdlib.h导致错误的争论进行辩论,这样做从来都不是有效的C ++,并且对于C也不是有效的C过去21年。

最佳做法:

C

  • 如果您使用-std=c89-ansi-dinosaur等进行编译,则不要进行投射。
  • 否则,请遵循您的编码标准。
    • 如果它允许void与对象指针之间进行隐式转换,请不要进行强制转换。
    • 如果不允许,则进行强制转换(这可能意味着您正在使用静态代码分析)。
    • 如果您没有编码标准,那就没关系了。投射无害,但会增加混乱。

C ++

  • 总是投射。
  • 避免使用void指针。
  • 最重要的是,避免使用malloc,而改用new / new[]