将“指向 const 的指针”转换为“指向 const VLA 的指针”

Posted

技术标签:

【中文标题】将“指向 const 的指针”转换为“指向 const VLA 的指针”【英文标题】:Cast "pointer to const" to "pointer to const VLA" 【发布时间】:2017-05-15 03:31:31 【问题描述】:

在这个 sn-p 中,指向 VLA 的指针用于更轻松地访问大型查找表:

#pragma GCC diagnostic warning "-Wcast-qual"

char
lookup(int a, int b, int c, char const *raw, int x, int y, int z)

    typedef char const (*DATA_PTR)[a][b][c];

    DATA_PTR data = (DATA_PTR)raw;

    return (*data)[x][y][z];

GCC 6.2.0 阻塞,而 Clang 4.0.0(trunk) 编译得很好,都启用了-Wcast-qual

In function 'lookup':
warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual]
   DATA_PTR data = (DATA_PTR)raw;
                   ^

无论哪种方式,代码都按预期运行。

我的猜测是 GCC 混淆了“指向 const 元素的 VLA 的指针”和“指向 const VLA 的指针”,但我正在达到...

有没有办法让 GCC 关闭而不用警告? 这是 GCC 错误吗?

EDIT1:

关于实际代码的详细信息:

struct table 
    int a;
    int b;
    int c;
    char *raw;
;

char
lookup2(struct table const *table, int x, int y, int z)

    typedef char const(*DATA_PTR)[table->a][table->b][table->c];

    DATA_PTR data;
    data = (DATA_PTR)table->raw; // GCC ok
    data = (DATA_PTR)(char const *)table->raw; // GCC raises -Wcast-qual

    return (*data)[x][y][z];

EDIT2:

就是这样...... C11 标准草案在 6.7.3/9 中说:

如果数组类型的规范包括任何类型限定符,则元素类型是如此限定的,而不是数组类型。

查看@hvd 答案。

-Wcast-qual 静音的一个技巧:

    DATA_PTR data = (DATA_PTR)(intptr_t)raw;

【问题讨论】:

“指向 const 元素的 VLA 的指针”和“指向 const VLA 的指针”是一回事。 const 数组是 const 元素的数组。看起来像一个错误。 为什么不让整个事情更安全一点,把raw变成char const (*raw)[a][b][c] @StoryTeller 我添加了代码的样子,但-Wcast-qual 仍然很奇怪。 @StoryTeller 这是一种解脱,谢谢。随时添加您的评论作为答案,以便我可以关闭问题。干杯! @diapir - 在 GCC 6.3 中也没有修复。显然-Wall -Wextra -pedantic 没有打开-Wcast-qual(叹气) 【参考方案1】:

这是 C 语言中长期存在的问题。原因相同

int array[2];
const int (*ptr)[2] = &array;

在 C 中无效(但在 C++ 中有效):这声明了一个指向 const 限定整数数组的指针,它不是 const 限定整数数组,因此指向类型的指针可以隐式转换为指向该类型的const 限定版本的指针的常规规则不适用。

在您的情况下,您正在从const char *(指向const 限定类型的指针)转换为char const (*)[a][b][c](指向非const 限定类型的指针),其中-Wcast-qual应该发出警告。

clang 只是从不费心实现 C 的这种特殊的奇怪之处,它使用 C++ 语义来处理 C 代码,即const 元素的数组本身也是const 限定的。

您通常可以通过将数组包装在 struct 中来解决它:

typedef struct  char d[a][b][c];  const *DATA_PTR;

但这不是 VLA 的选项。除了这里根本不使用多维数组或不使用-Wcast-qual之外,我认为没有合适的解决方法。

【讨论】:

摆弄警告然后......您是否知道在 C 中使用 C++ 规则(如 clang)可能存在潜在危险的情况?标准中没有理由这样做:6.7.3.9 如果数组类型的规范包括任何类型限定符,则元素类型是如此限定的,而不是数组类型。 @diapir 就const-正确性而言,C++ 规则是安全的,并且它也被提议用于 C(尽管我不知道它的状态)。如果您现在使用它,唯一的风险是您可能会意外编写无效/尚未有效的 C 代码,然后在使用严格的 C 编译器时导致错误。

以上是关于将“指向 const 的指针”转换为“指向 const VLA 的指针”的主要内容,如果未能解决你的问题,请参考以下文章

指向 const 指针(或指向 const 的指针)

const char*转char*怎么转?

const与指针的纠缠

C++ const总结

Qt4 C++ Pointer to const QList of pointers

CONST 常量