将 "pointer to const" 转换为 "pointer to const VLA"
Cast "pointer to const" to "pointer to const VLA"
在此代码段中,指向 VLA 的指针用于更轻松地访问大型查找 table :
#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 混淆了 "pointer to VLA of const elements" 和 "pointer to const VLA" 但我正在达到 ...
有没有办法在不摆弄警告的情况下关闭 GCC?
这是 GCC 错误吗?
编辑 1:
实际代码详情:
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];
}
编辑2:
就是这样……C11 标准草案在 6.7.3/9 中说:
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
查看@hvd 的回答。
一次破解即可静音 -Wcast-qual
:
DATA_PTR data = (DATA_PTR)(intptr_t)raw;
这是 C 中长期存在的问题。这与
的原因相同
int array[2];
const int (*ptr)[2] = &array;
在 C 中无效(但在 C++ 中有效):这声明了一个指向 const
限定整数数组的指针,它是 not 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
.
之外,没有合适的解决方法
在此代码段中,指向 VLA 的指针用于更轻松地访问大型查找 table :
#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 混淆了 "pointer to VLA of const elements" 和 "pointer to const VLA" 但我正在达到 ...
有没有办法在不摆弄警告的情况下关闭 GCC? 这是 GCC 错误吗?
编辑 1:
实际代码详情:
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];
}
编辑2:
就是这样……C11 标准草案在 6.7.3/9 中说:
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
查看@hvd 的回答。
一次破解即可静音 -Wcast-qual
:
DATA_PTR data = (DATA_PTR)(intptr_t)raw;
这是 C 中长期存在的问题。这与
的原因相同int array[2];
const int (*ptr)[2] = &array;
在 C 中无效(但在 C++ 中有效):这声明了一个指向 const
限定整数数组的指针,它是 not 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
.