2010-08-13 128 views
35

我一直对此很好奇 - 为什么在C++中我必须从malloc转换返回值,但不在C中?为什么C++需要为malloc()强制转换,但C不是?

这里是C++的作品为例:

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

这里是C++中的例子不工作(无施法):

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

我听说在C,实际上,从malloc()投射输出是一个错误。

任何人都可以对此主题发表评论吗?

+0

C++更敏感,需要您通过强制类型指定确切类型。 – Abhay 2010-08-13 14:30:56

+9

这不是直接关系到你的问题,但我认为你想'sizeof(int)',而不是'sizeof(int *)'。也就是说,使用'sizeof * int_ptr'会更好,它可以保证为'int_ptr'指向的任何类型分配适当的内存量。 – bcat 2010-08-13 14:31:30

+5

你为什么要在C++中使用malloc? – SoapBox 2010-08-13 14:31:53

回答

27

几点:

C允许空指针被隐式转换为任何其它对象指针类型。 C++没有。

将C中的malloc()的结果放在C中会抑制一个有用的诊断,如果您忘记包含stdlib.h或者没有在范围内具有malloc()的声明。请记住,如果C在没有事先声明的情况下看到一个函数调用,它将假定该函数返回int。如果您没有对malloc()的声明,并且您离开演员表,则会得到一个诊断,表明您试图分配不兼容的类型(int指向指针)。如果你输出了结果,你会抑制诊断并且可能会有运行时问题,因为不能保证将指针值转换为int并返回到指针会给你一个有用的结果。

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

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

+4

不管任何投射问题,现代编译器都不会输出malloc()缺失声明的警告吗? – 2010-08-13 15:01:36

+0

@Daniel:这也取决于你的警告等级。投射警告通常显示在比缺少声明更低的警告级别。 – 2010-08-13 15:36:52

+0

也许吧,但无论如何离开演员仍然是最好的做法。 – 2010-08-13 15:43:00

7

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

的一个原因,它的不赞成在C显式转换的malloc的返回值是,如果在当前编译单元不包括malloc签名,编译器将假定返回类型为int和它的隐式转换根据您指定的指针类型生成编译时警告,并立即解决。在明确演员的情况下,如果你犯了这个错误,将不会发出警告。

13

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

malloc()返回一个void*,它可以是任何东西,所以编译器不能保证你的转换会成功(或有意义)。通过使用明确的转换,你告诉编译器你正在做的事实际上是有意的。

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

+6

我可以隐式地将一个'int'转换成'bool'而没有问题。 – UncleBens 2010-08-13 16:54:38

+0

*“那是因为C++是一种强类型语言。”* ...和C不是!? – cdhowie 2017-04-12 15:56:46