c - 对于转换指针数组(例如 *array[]),为什么使用 (void**) 而不是 (void*)

标签 c kernighan-and-ritchie

以下代码片段来自 K&R 第 5-11 章:函数指针:

qsort((void**) lineptr, 0, nlines-1, 
   (int (*)(void *, void *)(numeric ? numcmp : strcmp));

我可以使用 (void*) 编译/运行代码,那么为什么 lineptr 要用 (void **) 进行转换呢?两个 Actor 之间是否存在任何内部差异,或者更多的是为了可读性? (void *) 仅转换数组,而 (void **) 转换数组和存储的指针?

我知道 **lineptr 相当于 *lineptr[] 并且 void 强制转换的原因是为了让编译器满意。

最佳答案

这很可能是错误的。

void* 是一个指向某物的指针。我们不知道它指向什么。您可以将任何指针强制转换为 void*。传递给 qsort 的比较函数必须猜测 void* 指向的实际类型是什么。如果做对了,就好了。如果出错,事情就会出错——这就是生活,也是程序员的责任。

void** 是指向 void* 数组的指针。这里有一个很大的区别:虽然您可以毫无问题地将 int* 转换为 void*,但 int* 数组绝对不是 void* 数组。 int* 和 void* 可以有不同的大小! C 标准非常清楚哪些类型的指针具有相同的表示形式:

  1. void* 和 char* 的任何变体(void** 不是 void* 的变体)
  2. 任何指向结构的指针
  3. 任何指向 union 的指针
  4. 任何指向不同符号的原始类型的指针(如 int、unsigned int)。

任何不在同一组中的指针都可以有不同的表示形式,因此强制转换可能会起作用,但 memcpy 或通过指向不同指针类型的指针读取值不起作用。

关于c - 对于转换指针数组(例如 *array[]),为什么使用 (void**) 而不是 (void*),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27661807/

相关文章:

c - 为什么这个 C 程序不提取转义的反斜杠?

C 编程 - K&R 示例 1.5.2 - 修改后的程序未按预期运行

c - 为什么 Kernighan 和 Ritchie 不将 int 包含在 main 函数中?

c - 检测到 glibc,realloc() : invalid next size:X

c - 不确定 K&R 中句子的正确性 - 指针算术 |释放程序

当 main() 退出时调用另一个函数

c - 如何在C语言中读取/解析输入?常见问题

c - 为什么 Kernighan 和 Ritchie 包含看似不必要的类型转换?

c - C 中的 IIR 滤波器实现

c - 使用以前未定义的宏时不会出现编译器错误