Cast"指向const"的指针to"指向const VLA"

时间:2016-12-30 21:24:42

标签: 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];
}

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;
                   ^

代码按预期运行。

我的猜测是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 answer。

沉默-Wcast-qual

    DATA_PTR data = (DATA_PTR)(intptr_t)raw;

1 个答案:

答案 0 :(得分:7)

这是C中一个长期存在的问题。这与

的原因相同
int array[2];
const int (*ptr)[2] = &array;

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

在您的情况下,您将const char *(指向const - 限定类型的指针)转换为char const (*)[a][b][c](指向非const的指针} -qualified type),-Wcast-qual应警告。

clang从不打算实现C的这种特殊奇怪性,它用C ++语义处理C代码,它说const元素的数组本身const - 也是合格的。

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

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

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