将"指向const的指针"转换为"指向const VLA的指针"

dia*_*pir 8 c pointers const c99 variable-length-array

在此代码段中,指向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];
}
Run Code Online (Sandbox Code Playgroud)

GCC 6.2.0扼杀它,而Clang 4.0.0(主干)编译得很好,两者都-Wcast-qual启用了.

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

代码按预期方式运行.

我的猜测是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];
}
Run Code Online (Sandbox Code Playgroud)

EDIT2:

所以它是...... C11标准草案在6.7.3/9中说:

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

见@hvd回答.

一个沉默的黑客-Wcast-qual:

    DATA_PTR data = (DATA_PTR)(intptr_t)raw;
Run Code Online (Sandbox Code Playgroud)

小智 7

这是C中一个长期存在的问题.原因也是如此

int array[2];
const int (*ptr)[2] = &array;
Run Code Online (Sandbox Code Playgroud)

是无效的在C(但将在C++中有效):这声明一个指针数组const-qualified整数,这是一个const整数-qualified阵列,所以正常规则的指针类型可以隐式转换到指向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;
Run Code Online (Sandbox Code Playgroud)

但这不是VLA的选择.除了不使用多维数组或不使用多维数组之外,我不相信有合适的解决方法-Wcast-qual.