2016-12-30 18 views
7

、VLAからポインタが大きなルックアップテーブルへのアクセスを容易にするために使用されます。キャストこのスニペットで「VLAをCONSTするポインタ」に「CONSTへのポインタ」

#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チョークしている間クラング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へのポインタ」と「VLAをCONSTへのポインタを」混乱が、私は到達しています...

が警告をいじることなく、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; 
+3

"const要素のVLAへのポインタ"と "const VLAへのポインタ"は同じものです。 const配列はconst要素の配列です。バグみたいです – emlai

+0

全体をもう少し型安全にし、 'raw'を' 'char const(* raw)[a] [b] [c]'にするのはなぜでしょうか? – StoryTeller

+0

@StoryTellerコードがどのように見えるかを追加しましたが、それでも '-Wcast-qual'は変です。 – diapir

答えて

6

これは

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

はCで無効である(ただし、Cに有効だろう、なぜ同じ理由だC.での長年の課題である++ ):これはconst - 修飾された整数の配列へのポインタを宣言します。ではないconst - 修飾された整数の配列です。したがって、型へのポインタを暗黙的にpoに変換できる通常の規則そのタイプのconst-修飾バージョンとの間には適用されません。あなたのケースでは

、あなたはについて警告することになっている-Wcast-qual、(非const -qualified型へのポインタ)char const (*)[a][b][c]に(const -qualified型へのポインタ)const char *から変換しています。

clangはCのこの特別な奇妙さを実装するのに悩まず、CコードをC++セマンティクスで扱います。つまり、const要素の配列自体はconst -qualifiedです。

あなたは、通常structに配列をラップすることによって、それを回避することができるだろう:

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

が、これはのVLAのためのオプションではありません。私は、ここで多次元配列を使用していないか、-Wcast-qualを使用していない以外の適切な回避策はないと考えています。

+0

警告を飛ばしています...あなたはインスタンスを認識していますか? _6.7.3.9配列型の指定に型修飾子が含まれている場合、要素型は限定されたものであるため、配列型ではありません._ – diapir

+1

@diapir C++のルールは、 'const'-correctnessがある限り安全です。C言語でも同様です(しかし、私はその状態を知りません)。厳密なCコンパイラが使用されたときにエラーを引き起こす無効/有効ではないCコードを誤って記述する可能性があります。 – hvd

関連する問題