2016-05-19 2 views
1

私は32ビットアーキテクチャでCを使用します。アレイインデックスの整数オーバーフロー

私がarray[-2147483635]を使用した場合、Cはなぜそれをarray[13]に変換しますか? 2の補数の

-214748363510000000000000000000000000001101b

あり、それはそれが13で、左のビットを取ると、それは 00000000000000000000000000001101bになるように0にそれを翻訳してい???

size_tにキャストされているとは思いません。 size_t-21474836354294967264に変換します。

+0

なぜあなたはそれが 'array [13]'に変換されると思いますか? – jotik

+0

私はそこに書いている魔女のアドレスを参照してください – jordan

+0

'array'の型は何ですか? – jotik

答えて

6

array[13]には翻訳されませんが、array[-2147483635]に正しく変換されます。ただし、未定義の動作が発生する可能性があります。例えば、32ビットx86上で、

char f(char * a) { return a[-2147483635]; } 
int g(int * a) { return a[-2147483635]; } 

のためのアセンブリは、次のようになります。

f: 
    pushl %ebp 
    movl %esp, %ebp 
    movl 8(%ebp), %eax 
    movzbl -2147483635(%eax), %eax 
    popl %ebp 
    ret 
g: 
    pushl %ebp 
    movl %esp, %ebp 
    movl 8(%ebp), %eax 
    movl 52(%eax), %eax 
    popl %ebp 
    ret 

は、オンライン例hereを参照してください。だから、char配列はすべてよく見えますが、整数配列(movl 52(%eax), %eaxは52が4 × 13)のオーバーフローを見ることができます。 32ビットシステムでは、インデックスが-2147483635 の要素は、任意の配列またはポインタに対してが存在しない可能性があるため、未定義の動作が原因です。配列の場合、で、配列の最初の要素の前のいくつかの要素を指すため、未定義の動作です。任意のポインタについて、最大値が2 または4294967296バイトのメモリしか持たず、インデックス -1または4294967295の最後のバイトを指しているとすると、-2147483635番目の要素は-4294967245である4294967295 - 8589934540であるメモリアドレス4294967295 + ((-2147483635)*sizeof(int))に存在しなければならない。このようなメモリアドレスは意味をなさない。

詳しくは、cppreferenceまたはC規格の§6.5.6(8)を参照してください。

+0

私はマイナスタイプを知ることができません?それがsize_tかunsigned intならば? なぜ整数オーバーフローが発生しましたか?私はインデックスにマイナスを置くので?プラスに変換する必要がありますか? – jordan

+0

@ jordan私は質問 – jotik

3

-2147483635は、下限が–2147483648であるため、4バイト符号付き整数の範囲内に収まります。

負のインデックスを持つ添字配列は、境界外のメモリにアクセスするため、未定義の動作です。 arrayが実際にポインタであり、十分に大きな連続領域のメモリの2147483635 * sizeof(int)バイトを超えている場合にのみ、この負のインデックスを使用できます。

+0

にあなたのコメントに関して私の答えを大幅に改善しました、なぜそれが13になるのですか?定義されていない動作があるので ? それは左のビットが0になるのを告げるのは正しいですか? – jordan

+1

@jordan:コンパイルしているコードを投稿してください。さらに、インデックスが「13」と評価されることをどのように確認できますか? –

+0

私はそれがそこに書くpleaceを見るので13確かにある 左のビットを取り、0をそこに置くことは難しいですか? – jordan

関連する問題