c - const 字符串动态数组的正确类型

标签 c visual-studio constants pointer-conversion

我一直认为 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/

相关文章:

检查(作为普通用户)管理进程是否正在运行(C,Windows)

c - 链表崩溃,c

C++、外部和 GCC

visual-studio - 如何从VS2022状态栏中删除 "Add to Source Control"按钮?

sql-server - Visual Studio 2010 中数据库开发的最佳实践?

编译器优化 : const on non-pointer function arguments in C

javascript - selenium 使用 javascript 定位没有 id 或 name 的元素

c# - System.Diagnostics.Debug.WriteLine 被跨过

pointers - 声明 const 指针为 int 吗?

c++ - 将临时绑定(bind)到非常量引用