void 指针:C 和 C++ 之间的区别

Posted

技术标签:

【中文标题】void 指针:C 和 C++ 之间的区别【英文标题】:void pointers: difference between C and C++ 【发布时间】:2010-12-16 17:57:36 【问题描述】:

我试图了解 C 和 C++ 在 void 指针方面的区别。以下是用 C 编译而不是 C++ 编译(所有编译都使用 gcc/g++ -ansi -pedantic -Wall 完成):

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

因为malloc 返回void*,C++ 不允许将其分配给int*,而C 允许这样做。

但是,这里:

void foo(void* vptr)



int main()

    int* p = (int*) malloc(sizeof(int));
    foo(p);
    return 0;

C++ 和 C 都可以毫无问题地编译它。为什么?

K&R2 说:

任何指向对象的指针都可以是 无损失地转换为void * 类型 的信息。如果结果是 转换回原来的指针 类型,原来的指针是 恢复了。

这很好地总结了 C 中关于 void* 转换的所有内容。C++ 标准规定了什么?

【问题讨论】:

GMan 正确解释了您收到错误的原因。也就是说,如果你正在编写 C++ 代码,你应该使用 new/new[] 和 delete/delete[] 而不是 malloc/calloc 和 free/free。 【参考方案1】:

在 C 中,与void* 之间的指针转换始终是隐式的。

在 C++ 中,从 T*void* 的转换是隐式的,但从 void* 到其他任何东西都需要强制转换。

【讨论】:

你能提供你的第二个声明的来源吗?它是用 C++ 标准编写的吗? 真的没什么好引用的。它在第 4.10.2 节中。它几乎说T* 可以转换为void*。它省略了反面,暗示你必须使用演员表。 @zaharpopov:查找 reinterpret_cast 或 static_cast @GMan:明确不说明从 void* 转换意味着不可能做到这一点(即不允许(隐式)从 void* 转换为任何其他指针类型)。然后通过查看强制转换运算符的定义,您可以了解这些运算符可以对对象做什么。他们对将 void* 转换为其他类型的定义非常清楚。 @GMan:如果“在 C 中,指针转换总是隐式的”你的意思是与void * 之间的转换,那么你是对的。否则,在指针转换方面,C 与 C++ 一样严格。例如,在 C 中没有从 char *int * 的隐式转换。从历史上看,习惯上在 C 编译器中将指针转换错误报告为“警告”,这导致了一个关于 C 据称允许所有和任何隐式指针转换。然而,这只是一个神话。【参考方案2】:

C++ 的类型比 C 更强。许多转换,特别是那些暗示对值的不同解释的转换,都需要显式转换。 C++ 中的 new 运算符是一种类型安全的在堆上分配内存的方法,无需显式强制转换。

【讨论】:

【参考方案3】:

了解指针类型转换实际上并不需要执行额外的 CPU 指令是很有用的。在编译期间对它们进行分析,以了解开发人员的意图。 void * 是一个不透明的指针。它只是说指向对象的类型是未知的。 C 是弱类型的。它允许在 (void *) 和任何 (T*) 之间隐式进行直接转换。 C++ 是强类型的。从 (void *) 到 (T*) 的转换对于强类型语言来说并不是很好的例子。但是 C++ 必须保持与 C 的向后兼容,因此它必须允许这样的转换。指导原则是:显式优于隐式。因此,如果您希望将 (void*) 转换为某个特定的 (T*) 指针,则需要在代码中显式编写。从 (T*) 到 (void*) 的转换不需要显式转换,因为直接对 (void*) 指针无能为力(尽管可以调用 free())。因此 (T*) 到 (void*) 的转换非常安全。

【讨论】:

指针转换是否需要 CPU 指令是一个实现细节。在 C 和 C++ 语言中,绝对没有任何东西需要这种转换纯粹是概念性的(即不需要 CPU 指令)。相反,这两种语言都是专门制定的,以允许对不同的指针类型进行不同的表示。虽然“理解”在典型情况下,转换实际上在 CPU 级别上没有任何作用可能确实有用,但编写依赖于该假设的 C 或 C++ 代码是一个严重的错误。 ...而且我不明白“保持向后兼容”的意义。 C++ 需要显式转换才能从 void * 转换。那已经向后兼容 C。 C++ 并不完全向后兼容 C。它只是提供了在必要时尽可能简化迁移的方法。从弱类型转换到强类型自然会导致兼容性问题。 C++ 只是尝试提供简单的方法(例如对 void 指针进行显式类型转换)来简化迁移。 @AndreyT:为了再次强调你的观点,派生类和基类之间的转换(尤其是多重继承)可能需要 CPU 才能将指针移动到内存中对象的适当部分. C++ 遭受与 C 相同的隐式类型提升规则这一事实使得 C++ 也是一种非常弱类型的语言。除了 void 指针之外,“强类型”还有更多内容。

以上是关于void 指针:C 和 C++ 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

c 和 c++ 中的指针之间有啥大的区别吗? [关闭]

[转载]C++中引用与指针的区别(详细介绍)

C++指针和&Pointer之间的区别[重复]

NULL0nullptr 区别分析

C语言中的.c和.cpp有啥区别?

在c ++函数中返回地址和返回指针之间的区别[重复]