我一直认为 const char **x
是用于动态分配的 const 字符串数组的正确类型,如下所示:
#include <stdlib.h>
int main()
{
const char **arr = malloc(10 * sizeof(const char *));
const char *str = "Hello!";
arr[0] = str;
free(arr);
}
但是,当使用 VS2017 编译此代码时,我在 free
行收到此警告:
warning C4090: 'function': different 'const' qualifiers
我的代码有问题吗? FWIW,当我用 GCC 编译时,我没有收到任何警告,即使使用 -Wall -Wextra -pedantic
。
最佳答案
您的代码没有任何问题。相关规则可在此处的 C 标准中找到:
6.3.2.3 Pointers
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
意味着任何指向对象类型(指向变量)的指针都可以转换为 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 是一个非常令人困惑的主题。
当我们有一个 const 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
:
error: passing argument 1 of 'free' discards 'const' qualifier from pointer target type
显然,Visual Studio 给出了错误的诊断。或者您将代码编译为 C++,它不允许隐式转换到/从 void*
。
关于c - const 字符串动态数组的正确类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42968546/