您的代码没有任何问题。相关规则可在此处的 C 标准中找到:
6.3.2.3 指针
指向 void 的指针可以转换为指向任何对象类型的指针或从指向任何对象类型的指针转换。指向任何对象类型的指针都可以转换为指向 void 的指针并再次返回;结果应与原始指针比较。
对于任何限定符 q,指向非 q 限定类型的指针可以转换为指向该类型的 q 限定版本的指针;存储在原始指针和转换指针中的值应比较相等。
这意味着任何指向对象类型(指向变量)的指针都可以转换为 void 指针,除非该指针是合格的(const 或 volatile)。所以这样做很好
void* vp;
char* cp;
vp = cp;
但是这样做是不行的
void* vp;
const char* cp;
vp = cp; // not an allowed form of pointer conversion
到目前为止,一切都很好。但是当我们混合指针到指针时,const
-ness 是一个非常令人困惑的主题。
当我们有 aconst char** arr
时,我们有一个指向常量 char 的指针(提示:从右到左读取表达式)。或者在 C 标准胡言乱语中:指向类型的限定指针的指针。arr
虽然它本身不是一个合格的指针!它只是指向一个。
free()
需要一个指向 void 的指针。我们可以向它传递任何类型的指针,除非我们传递一个合格的指针。const char**
不是一个合格的指针,所以我们可以很好地传递它。
指向类型指针的限定指针应该是char* const*
.
注意当我们尝试这个时 gcc 是如何抱怨的:
char*const* arr = malloc(10 * sizeof(char*const*));
free(arr);
gcc -std=c11 -pedantic-errors -Wall - Wextra
:
错误:传递“free”的参数 1 会从指针目标类型中丢弃“const”限定符
显然,Visual Studio 给出了不正确的诊断。或者,您将代码编译为 C++,它不允许隐式转换到/从void*
.