【问题标题】:What is the purpose of void pointers?空指针的目的是什么?
【发布时间】:2021-05-08 08:07:17
【问题描述】:

为什么需要空指针,只要可以将任何指针类型转换为任何指针类型,即:

char b = 5; 
int*a = (int*)&b;//both upcasting

int b = 10;
char*a = (char*)b;//and downcasting are allowed

?

另外,为什么在使用 malloc/calloc/realloc 时不需要强制转换?

【问题讨论】:

标签: c pointers casting void-pointers


【解决方案1】:

void 指针对于创建通用 API 非常有用。您可能会想到qsort 函数,它可用于对任何类型的数组进行排序。如果 API 不知道指针的具体类型,则可以使用void 指针。

void qsort(
   void *base,
   size_t number,
   size_t width,
   int (__cdecl *compare )(const void *, const void *)
);

关于分配函数,也是一样的。 C 运行时不知道有效对象的类型。但这不是问题,因为用户可以使用通用指针void

所以void 指针被认为是泛型指针,对于多态非常有用,这就是 C 语言强制转换为 void 的原因。

【讨论】:

    【解决方案2】:

    “为什么需要 void 指针,只要可以转换任何指针类型”。

    然后,alloc 函数将不得不使用共同的分母,例如 char。但是,如果必须转换为我们真正需要的任何东西,那将是令人困惑的。 “void”仅表示“一堆字节”。

    【讨论】:

      【解决方案3】:

      可以将任何指针类型转换为任何指针类型

      不完全是。 void * 被定义为将任何对象指针1 转换为void * 并以等效值再次返回。它不需要任何演员表。

      在不太常见的架构中,其他一些指针的大小和范围可能小于void *。在其他指针类型之间进行强制转换可能会丢失必要的信息。

      void * 提供了一个通用的object指针类型。

      void *p = any_object_pointer; // No casts required
      any_object_pointer = p;       // No casts required
      

      char * 可以替代 void *,除了与其他对象指针的转换需要强制转换。


      OP 的 char b = 5; int*a = (int*)&b; 存在未定义行为的风险,因为 int * 的对齐需求可能超过 char *


      1函数指针可能比void*宽。 void * 和其他指针是对象指针。 C 缺乏真正通用的指针类型。

      【讨论】:

      • 需要注意的是,改变指针类型并不会改变指向对象的类型,因此,在任意类型的指针之间进行转换通常是不安全的。
      • 确实,我看到 C 需要一个不应该显式转换的通用类型指针。尽管如此,我不明白为什么转换为特定类型的指针是有风险的,只要指针类型仅在指针算术方面很重要,因为指针指向内存位置而不管它们的类型如何。
      • 另外,也许我应该打开另一个主题,但我看不到强制转换本身的目的,只要指针类型仅在涉及指针算术时才重要,因此,传递一个 char* 为例如,一个 int* 不能破坏内存的内容。
      • @pauk “只要指针类型仅在指针算术方面很重要”,这是不正确的。 1)“例如将 char* 传递给 int*”会产生问题。示例:当int * 仅适用于偶数地址,char * 可以处理前夕/奇数地址。 2) 类型允许优化——研究抗锯齿,因为编译器“知道”通过double * 操作对象不会通过int * 改变某些东西。还研究restrict 3) 强制类型检查失败。这种弱类型检查属于 C 的前辈——我们没有听说过这是有充分理由的——太容易编码错误。
      • 我理解得更好。谢谢
      猜你喜欢
      • 2011-05-19
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 2018-03-15
      • 2012-01-21
      • 1970-01-01
      相关资源
      最近更新 更多