为什么我们不能隐式地从void *赋值给C ++中的任何其他类型,但它在C中是首选?

根据这个

最好不要在C中 强制转换malloc ,因为如果转换malloc ,则会隐藏将被标记的错误,导致很难找到错误。 此外,在维护期间,如果指针的类型发生变化但铸件没有改变,则再次发现很难找到错误。 最有经验的程序员选择的方法是:

p = malloc ( n * sizeof *p ); 

malloc没有强制转换,因为不需要一个,而不是使用sizeof(type)来确定块的大小,而是使用sizeof * ptr 。 通过解除引用指针并获取其大小,可以给出正确的值,而不必担心如果指针的类型改变则修改分配请求。

但它不会在C ++中编译。 为什么?

这意味着如果malloc的返回被转换,那么将被标记的错误被隐藏?

它不会在C ++中编译。 为什么?

因为C和C ++是不同的语言。

C标准允许void *和其他指针类型之间的隐式转换。 它们不被C ++标准所允许。 在C中,演员阵容是不必要的,并且没有基本的编程指南“不要重复自己”,而在C ++中,语言需要演员表(这不是偏好问题)。

这意味着如果malloc的返回被转换,那么将被标记的错误被隐藏?

隐式函数声明不再是C语言的一部分,但许多编译器继续支持它作为与旧代码库兼容的扩展。 如果C函数没有原型,则假定返回int 。 如果你无意中将#include 从代码中删除但是调用malloc ,编译器可能会认为它返回int而不是void * [1]。 使用显式强制转换,假定的int结果将转换为void * ,这通常可能导致无效指针。 这很糟糕,可能导致难以诊断的运行时故障。

另一方面,如果您没有显式强制转换,则在编译时会收到警告或错误,指向错误的确切来源,这更容易诊断和修复。[2]


  1. 实际上,与使用返回指针(或其他类型)的函数相比, malloc不是问题,因为许多编译器都知道malloc并专门处理它。

  2. 在实践中,一些现代编译器实际上会警告你是否有演员表,但是肯定仍在使用的编译器如果演员阵容存在则不会发出警告,从而导致合理的偏执和防守编程。

但它不会在C ++中编译。 为什么?

在使用void*作为通用指针的便利性和防止无效类型转换的安全性之间进行权衡。

在C中, void*被广泛使用,因为它是编写通用代码的唯一合理方式; 因此,在该语言中,为方便起见,它可以隐式转换为另一种指针类型。

在C ++中,有类型安全的编写通用代码的方法,因此很少使用void* ; 特别是,你使用type-safe new来分配和初始化一个对象,而不是malloc来分配原始内存并假装它包含一个对象。 因此,在该语言中,禁止从void*隐式转换以提供更强的类型安全性。

这意味着如果malloc的返回被转换,那么将被标记的错误被隐藏?

线索在上一句话中:

除非在未包含声明malloc的标头stdlib.h ,否则没有任何问题

在(较旧的方言)C中,你可以调用一个尚未声明的函数; 隐式声明一个返回类型为int的函数。 因此,如果您在不包含标头的情况下调用malloc ,则会得到错误地认为它返回int 。 如果没有强制转换,当您尝试将其分配给指针时,会出现编译器错误。 使用强制转换,代码将被编译,可能会产生模糊的运行时错误和冗长的调试会话。

在C ++(和现代C)中,所有函数必须在使用前声明,因此即使您出于某种原因使用了malloc ,也不会发生此错误。

它在C ++语言中是不允许的,因为C ++具有类型安全性

它与类型安全有关。 特别是C允许从void*到其他类型的隐式转换,但c ++没有,这就是它在C中编译而不是C ++的原因。 这是C和C ++不同的方式之一。 C不是C ++的子集。

在c ++中,你应该使用new而不是malloc 。 New做了类型安全分配来解决这个问题。