我一直对这个问题很好奇 - 为什么在C++中,我必须强制转换来自malloc
的返回值,但在C中不需要?
以下是在C++中有效的示例:
int *int_ptr = (int *)malloc(sizeof(int*));
以下是不使用强制转换的 C++ 示例,但无法正常工作:
int *int_ptr = malloc(sizeof(int*));
我听说在C语言中,实际上将malloc()
的输出强制转换是个错误。
有人能对这个话题发表评论吗?
几点需要注意:
C语言允许将空指针隐式转换为任何其他对象指针类型。C++不允许。
在C中对malloc()
的结果进行强制转换将抑制有用的诊断,如果您忘记包含stdlib.h或其他没有声明malloc()
的作用域,则会出现此问题。请记住,如果C看到一个函数调用而没有先前的声明,它将假定该函数返回int
。如果您没有malloc()
的声明并且省略了强制转换,您将得到一条有关尝试分配不兼容类型(int到指针)的诊断信息。如果强制转换结果,您将抑制诊断,并可能在运行时遇到问题,因为不能保证将指针值转换为int,再转回指针将给您一个有用的结果。
如果您正在编写C ++代码,则应该使用new
和delete
而不是malloc()
和free()
。是的,是的,我听过所有人想要将其代码编译为C和C ++的原因,但是使用正确的内存管理工具来处理语言的好处优于维护两个版本的成本,在我看来。
注意:C89标准中添加了void *
类型;早期版本的C将malloc()
返回为char *
,因此在这些版本中,如果要将结果分配给不同的指针类型,则需要强制转换。然而,几乎每个人都支持至少C89标准,因此您遇到这些旧实现的可能性非常低。
void*
的转换都是允许的;从子类到其超类的转换也是允许的。所有其他转换都必须显式地进行,这样告诉编译器“我知道自己在做什么,这不是一个错误”。
malloc()
返回一个void*
,它可能是任何东西,因此编译器无法保证您的转换将成功(或有意义)。通过使用显式转换,您告诉编译器您正在执行的实际上是有意的。int i = 1.3; float f = ULONG_MAX;
编译没有错误。将Derived*
转换为Base*
由于数组而不安全。C++允许它,C不允许。 - melpomeneC语言支持将 void*
隐式转换为其他指针类型,而C++不允许这样做。
在C语言中,建议避免显式转换 malloc
返回值的类型,因为如果当前编译单元未包含 malloc
函数签名,编译器会假设其返回类型为 int
,并将其隐式转换为你所分配的指针类型,从而导致编译时警告,提醒你立即解决该问题。如果进行显式转换,就算犯了这个错误,编译器也不会发出警告。
C语言的类型规则非常宽松,而C++则稍微严格一些。在这种情况下,区别在于C允许对象指针和void
指针之间的隐式转换/赋值,而C++不允许。
实际上,旧式C甚至鼓励将对象指针隐式转换成/从void
指针,作为旧式通用C编程的一部分。由于C++获得了函数重载和模板等功能,因此从未需要void
指针。在C++中使用void
指针通常是可疑的。
关于关于强制转换malloc
结果会导致错误(如果没有包含stdlib.h
),这个老生常谈的争论,这在过去21年里既不是有效的C++也不是有效的C。
最佳实践:
C
-std=c89
、-ansi
或-dinosaur
等进行编译,则不要进行强制转换。void
和对象指针之间进行隐式转换,则不要进行强制转换。C++
void
指针。malloc
,而改用new
/new[]
。
sizeof(int)
而不是sizeof(int*)
。话虽如此,最好使用sizeof *int_ptr
,这可以确保你为指向的任何类型的int_ptr
分配了正确的内存量。 - bcatvoid*
或malloc()
几乎肯定是一个错误。 - Mike Seymour