3
void Test2()
{   
    int c=8;
    int b=7;
    int d=9;
    int *a; 

    a = &b;
    a+=sizeof(int); //I supposed that *a should points on variable d after this 

    cout << "b\t" << &b << "\t" << b << endl;
    cout << "a\t" << a  << "\t" << *a << endl;
    cout << "c\t" << &c  << "\t" << c << endl;
    cout << "d\t" << &d  << "\t" << d << endl;
}

*aは変数dを指していると思いました。なぜなら、bd (私が思ったように) はローカル変数のスタックの近くにあるからです。しかし *a は別のアドレスを指しているので*a != d 私の質問はなぜそうなのか? Visual Studio 2010 の機能ですか、それとも他の機能ですか?

4

4 に答える 4

9

いいえ、未定義の動作と呼ばれる C++ の機能です。所有している配列の外側 (または配列の境界の 1 つ上の位置) でポインター演算を実行することはできません。

はすでに であるa += 1ため、これを機能させることができます。したがって、次の整数を指すようになります。右に整数分移動します。aint*+= 1a+=sizeof(int)sizeof(int)

 +------+------+------+------+------+
 |      |      |      |      |      |      
 +------+------+------+------+------+
    ^      ^                    ^
    |      |                    |
    a     a+1               a+sizeof(int) (assuming sizeof(int) == 4)

繰り返しますが、技術的には未定義です。

于 2012-09-13T07:28:55.507 に答える
7

初心者にとっては、ポインタ演算があなたが思っているように機能するとは思いません。sizeof(int)ポインタはすでにへのポインタであるため、行う必要はありませんint。コンパイラは、a++4バイト進む必要があることを認識しています。

第二に、いいえ、ローカル変数を指すことはできません。コンパイラがローカル変数をメモリ内のどこに配置したか、その存続期間、またはメモリ内にあるかどうかさえわからないためです。コンパイラは、多くのローカル変数をCPUレジスタに最適化します。

編集:はい、有効なコメントに従って、ローカル変数へのポインターを取得でき、コンパイラーは正しいことを実行することを明確にする必要がありますが、完全に最適化されている可能性があるため、ポインター演算を使用することはできません。

于 2012-09-13T07:31:43.793 に答える
3

すべての変数が思いどおりに配置されていると仮定することはできません。また、このようにポインター演算を使用することもできません。安全に使用する唯一の方法は、配列の境界内で使用することです。また、a+=sizeof(int)次の整数を指すように移動するのではなく、整数だけ移動しsizeof(int)ます。

ここでは UB に依存しているため、特定の結果は期待できません。実際には、segfault が発生することさえあります。

于 2012-09-13T07:28:51.527 に答える
0

いいえ、VisualStudio2010の機能ではありません。ポインタの算術演算は、未定義の動作を示しています。

通常、配列の要素を指す場合にのみインクリメント/デクリメントを使用します

于 2012-09-13T07:31:22.200 に答える