【问题标题】:Why is char** (or any T**) to void** cast invalid?为什么 char** (或任何 T**) to void** cast 无效?
【发布时间】:2015-07-10 19:04:29
【问题描述】:

Python C Module - Malloc fails in specific version of Python 的第一条评论中,@user694733 提到将char** 转换为void** 是无效的。我阅读了Invalid conversion from Foo** to void** - why is implicit type conversion allowed to void* but not to void**?http://c-faq.com/ptrs/genericpp.html,但有对标准的引用,但没有实际示例,在这种情况下,这可能是不正确的,从而导致错误。考虑例如void**double** 或反之亦然,是否有可能出错的情况?为什么(从技术上讲,不仅仅是因为它是 UB)?

【问题讨论】:

  • 请清楚地说明问题,而不是强迫任何愿意解决您的请求的人,阅读 2-3 个额外的帖子。
  • 强制转换和void* 的行为在 C 和 C++ 中是不同的。请选择一个。
  • 首先,C 和 C++ 中的术语“转换”是指显式转换。从T **void ** 的显式转换通常是有效的。其次,对应转换的潜在问题与著名的FAQ条目中描述的T ** -> const T **转换的底层结构完全相同:isocpp.org/wiki/faq/const-correctness#constptrptr-conversion
  • 演员表无效;任何对象指针类型都可以转换为任何其他对象指针类型,如果存在对齐错误,则只有UB,这在这种情况下不太可能(大多数系统具有相同对齐要求的所有指针)

标签: c++ c pointers casting


【解决方案1】:

如果允许,它会在类型系统中创建一个漏洞:

T* ptr;
void **vptr = &ptr; // &ptr is of type T**
int value;
*vptr = &value;     // &value is int*, can be converted to void*

此时,ptr(根据类型系统是指向T 的指针)正在指向value,即int。虽然该语言允许您绕过类型系统,但您必须明确请求它。隐式转换旨在避免此类问题。

【讨论】:

    【解决方案2】:

    最大的实际问题是多重继承。当您使用指向具有多个基类的类的指针时,指针的实际值将取决于指针的类型,并且当您从一种指针类型分配给另一种指针类型时,编译器会插入修复代码来调整它。当您拥有指向该指针的指针时,编译器将不再有机会进行这些修复,因此该操作被标准禁止。

    【讨论】:

      【解决方案3】:

      但有参考标准,但没有实际示例,在这种情况下,这可能是不正确的,导致错误

      这不准确。您提到的页面http://c-faq.com/ptrs/genericpp.html 指向另一个页面http://c-faq.com/null/machexamp.html,其中包含针对不同类型具有不同指针大小的机器的示例:

      Data General 的 Eclipse MV 系列具有三种体系结构支持的指针格式(字、字节和位指针),其中两种由 C 编译器使用:用于 char * 和 void * 的字节指针,以及用于其他所有内容的字指针.由于历史原因,在 32 位 MV 线从 16 位 Nova 线演变而来的过程中,字指针和字节指针在字的不同位置具有偏移、间接和环保护位。将不匹配的指针格式传递给函数会导致保护错误。最终,MV C 编译器添加了许多兼容性选项来尝试处理存在指针类型不匹配错误的代码。

      【讨论】:

      • 那么,如何创建一个接收泛型类型的双指针作为参数的函数?
      • @APJo 正如这里所说的c-faq.com/ptrs/genericpp.html,具有void** 参数的函数没有问题,但是这样的函数实际上应该知道底层指针类型,当它从中读取数据时双指针。也许这些信息可以作为单独的参数或通过其他方式传递。
      • 我目前正在制作int safe_malloc(void** toalloc, size_t bytes) - 它似乎也可以直接工作,尽管目前我只将它用于char *s - 他们的严重问题是练习?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-31
      • 2019-06-07
      • 2019-04-26
      • 2023-04-05
      • 1970-01-01
      相关资源
      最近更新 更多