2

V1.8 z/OS XL C コンパイラーを使用し、INFO(ALL) を使用して警告を表示すると、以下のコードの 4 行目に次の警告が表示されます。

WARNING CCN3196 Initialization between types "const int** const" and "int**" 
                is not allowed.


1  int foo = 0;
2  int *ptr = &foo;

3  const int * const fixed_readonly_ptr = ptr;

4  const int ** const fixed_ptr_to_readonly_ptr = &ptr;

なぜこの警告が表示されるのか、頭を悩ませることはできません。const int への const ポインターに int ポインターを割り当てることができる場合 (3 行目)、int ポインターのアドレスを const ポインターに const int へのポインターに割り当てることができないのはなぜですか? 私は何が欠けていますか?

上記のコードは、少量のコードで発生している問題を示しているだけのスリム化された例であることに注意してください。実際のコンテキストは、構造体 (struct s** const) へのポインターへの const ポインターがあり、それを関数への引数として渡していることです。関数のパラメーターは、const struct (const struct s** へのポインターへの const ポインターとして定義されています)定数)。これは、関数が構造体のデータを変更せず (したがって最初の const)、渡されたアドレスを常に保持するポインター パラメーター (したがって 2 番目の const) を変更しないためです。指しているポインターの値は、途中で変更される場合があります (これが、** の間に 3 番目の const がない理由です)。

4

3 に答える 3

5

これは型安全性違反です。このコードを考えてみてください(constポインターとポインティのどちらに適用されるかを明確にするために少しシャッフルしましたが、意味的にはまったく同じことを意味します):

int* p = 0;
int const** pp = &p; // presumably ok

int const c = 123;
*pp = &c; // okay, &c is int const*, and *p is int const* lvalue

*p = 666; // okay, *p is int lvalue

// wait, so we just changed the value of (const) c above, with no const_cast!
于 2009-09-23T20:26:09.013 に答える
3

C の規則では、何かへのポインターを const へのポインターに変換できますが、その何かはチェーンのさらに下にある const および volatile 修飾子を含め、まったく同じ型でなければなりません。

このルールの根拠は、これら 2 行のうちの 2 行目が許可された場合です。

int *ptr;

const int ** const fixed_ptr_to_readonly_ptr = &ptr;

次に、これを使用して、キャストなしで型の安全性を破ることができます。

const int i = 4;

// OK, both sides have type const int *
*fixed_ptr_to_readonly_ptr = &i;

// the value of fixed_ptr_to_readonly_ptr is still &ptr
// the value of ptr is now &i;

*ptr = 5;

// oops, attempt to change the value of i which is const
于 2009-09-23T22:03:41.653 に答える
0

これはタイプ セーフ違反です。代わりに const int * const * を使用することをお勧めします。http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17を参照してください。

于 2009-09-23T22:12:03.423 に答える