-2

私はこの機能を持っています:

void func(int index, struct foo b[])
{
    // ...
    a[0][0] = b[index].c[0];
    // ...
}

ただし、関数が index で呼び出される場合もあります-2

a[0][0] = b[-2].c[0];

-2 は範囲外だと思います。クラッシュすることもありますが、そうでないこともあります。

配列bの先頭アドレスが0xffd9cda4の場合、b[-2]のアドレスは?
0xffd9cda4 + 0xfffffffe = 0x1ffd9cda2? 0x1ffd9cda2 は有効ですか?

Linux 64ビットで実行されています。

4

3 に答える 3

2

bアドレスで始まるメモリブロックを占有する配列があります&b[0]。のアドレスが何であるかを調べようとさえしないでくださいb[-2]。これは明らかに、この配列によって占有されているメモリブロック内にないためです。

配列の境界外のメモリにアクセスしようとすると、未定義の動作が発生します。


bまた、この関数の本体内で配列のサイズを取得することはできないことに注意してください。

void func(int index, struct foo b[]) {
    // ...
}
于 2013-02-22T21:31:13.393 に答える
2

境界外の配列にアクセスすると、未定義の動作が発生します。ただし、C には自動配列境界チェックがありません。したがって、これによりクラッシュが発生する可能性がありますが、クラッシュするという保証はありません。多くの場合、たまたまメモリ内で隣接して配置されているオブジェクトにオーバーフローします。

bが配列ではなくポインターである場合b[-2]、有効な場合があることに注意してください。例えば

typedef struct foo {
   int c[5];
} foo_struct;
foo_struct x[10];
foo_struct *b = &x[3];

あなたが今行う場合:

a[0][0] = b[-2].c[0];

次のようにするのと同じです:

a[0][0] = x[1].c[0];

この場合の関連する配列境界は、x.

于 2013-02-22T21:53:33.420 に答える
0
b[-2]

と同じです

*(b - 2)

これは明らかに間違っています。未定義の動作、所有していないメモリへのアクセス。UB は、プログラムがクラッシュするという意味ではなく、プログラムの動作が未定義であることを意味します。

于 2013-02-22T21:45:52.530 に答える