3

重複の可能性:
C /C++がconstの値を変更する

次のプログラム:

int main()
{
    const int x = 10;
    int * p = (int *)&x;
    *p = 12;
    cout<<x<<endl;
    cout<<*p<<endl;
    return 0;
}

次の出力を提供します。

10
12

&xを(int *)にキャストするとどのような効果があり、xの値がまだ10であるのはなぜですか?12になると思っていました。

別の疑問

なぜint**をintconst**にキャストできないのですか?むしろ、この操作は有効です

void f(int const ** p);
void g(int const * const * p);

int main()
{
    int ** p = /*....*/
    f(p);   //Error
    g(p);   //OK
}

適切な例でこれを理解するのを手伝ってくださいありがとう!!!

4

4 に答える 4

8

として宣言された変数を変更することにより、未定義の動作を呼び出していますconst。一部の結果は他の結果よりも妥当ですが、プログラムからの正当な出力である結果はすべてあります。

コメントで述べたように:

10は最適化が原因である可能性があります。コンパイラーはそれxがconstであることを知っているので、以下を呼び出すことができます。

cout << 10 << endl;

それ以外の:

cout << x << endl;

それほど明確ではないのは、コンパイラが2番目の出力を次のように最適化するかどうかです。

cout << 12 << endl;

確実に知るには、生成されたアセンブラを確認する必要があります。しかし、プログラム全体が未定義の動作を呼び出しているため、コンパイラーは、それが何をするかに関係なく正しいです。

于 2012-05-11T15:06:28.260 に答える
2

コンパイラーは、リテラル値がに割り当てられると、リテラル値に置き換えますconst int。事実上、プログラムは次のようになります。

        cout<<10<<endl;
        cout<<*p<<endl;
于 2012-05-11T15:03:10.560 に答える
1

主な質問の時点で、それはすでに答えられています:定数オブジェクトの変更は未定義の動作です。

2番目の質問については、許可された場合、誤ってconst-correctnessを壊す可能性があることを考慮してください。

const int k = 10;
void f(int const ** p) {
    *p = &k;                   // Valid, p promises not to change k
}
void g(int const * const * p);

int main()
{
    int *p;
    int ** pp = &p;
    f(pp);                     // If allowed: p points to k!!!
    p = 5;                     // Modifying a constant object!!!
    g(pp);                     //OK
}

の場合g、関数のシグニチャは中間ポインタが変更されないことを約束するため、コンパイラはそれが変更されないことを認識しgます。つまり、定数オブジェクトを指す*ppようにすることはできず、const-correctnessが保証されます。 。*ppp

于 2012-05-11T15:48:40.853 に答える
0

さて、それは興味深い質問です。xのconstプレフィックスを削除すると、希望どおりの結果が得られます。

int main()       
{               
 int x = 10;               
 int * p = (int *)&x;               
 *p = 12;              
 cout<<x<<endl;              
 cout<<*p<<endl;               
 return 0;      
}

xの値の変化を防ぐのはconstマークだと思います。

于 2012-05-11T15:29:00.097 に答える