web-dev-qa-db-ja.com

Cでの二重ポインターのconst-correctness警告

非constデータへのポインターは、同じタイプのconstデータへのポインターに暗黙的に変換できます。

int       *x = NULL;
int const *y = x;

追加の間接参照と一致するように追加のconst修飾子を追加しても、論理的には同じように機能するはずです。

int       *      *x = NULL;
int       *const *y = x; /* okay */
int const *const *z = y; /* warning */

ただし、-Wallフラグを使用してGCCまたはClangでこれをコンパイルすると、次の警告が表示されます。

test.c:4:23: warning: initializing 'int const *const *' with an expression of type
      'int *const *' discards qualifiers in nested pointer types
    int const *const *z = y; /* warning */
                      ^   ~

const修飾子を追加するのはなぜですか「ネストされたポインター型の修飾子を破棄します」?

55
Michael Koval

constを1レベルだけ追加できる理由は微妙で、 comp.lang.c FAQの質問11.1 で説明されています。

簡単に言えば、あなたの例と密接に関連しているこの例を考えてみましょう:

const int i;
int *p;
int const **z = &p;
*z = &i;
/* Now p points to i */

Cは、最初にポイントされたレベルで破棄修飾子への割り当てのみを許可することにより、この問題を回避します(したがって、ここでのzへの割り当ては許可されません)。

第2レベルのconst*zへの割り当てが許可されないことを意味するため、正確な例ではこの問題は発生しません。 C++wouldは、この正確なケースでそれを許可しますが、Cのより単純なルールでは、ケースと上記の例を区別しません。

47
caf

他の回答によってリンクされているFAQエントリは、次のコードが許可されない理由を説明しています:

int **x = whatever;
const int **z = x;

ただし、コードconst int *const *z = x;はまったく異なり、FAQで指摘された同じ欠陥に悩まされることはありません。

実際、後者のコードには概念的に何も問題はありません。許可されていないのはC仕様の欠陥に過ぎず、Cプログラマはコードに醜いキャストを含める必要があります。

CがC++と同じ規則を使用することは可能でした。しかし、C標準委員会はそれを行うことを決定しませんでした。

8
M.M