2016-10-06 4 views
3

以下のコードでは、gccはインデックスについて警告していません。その理由は何ですか?int(* foo)[3]のインデックス4にアクセスすると警告が表示されない

int foo[3] = {1,2,3}; 
int (*bar)[3]; 

int main(void) { 
    bar = &foo; 
    foo[42] = 42; 
    (*bar)[42] = 42; 
    return 0; 
} 

私だけbarためfooないためにエラーが発生します。どうして?

$ gcc -std=c99 -Wall -O2 -Wpedantic -Wextra test.c 
test.c: In function ‘main’: 
test.c:6:8: warning: array subscript is above array bounds [-Warray-bounds] 
    foo[42] = NOPE; 
     ^

私はbar = fooを書かれており、int* barとしてbarを宣言したが、私はしませんでしたと...他のよりも一つの解決策優れている理由を私は知らないが、これは別であることができました面白い質問。

+1

ポインタは、単にメモリアドレスです。それはそれが限界であることとそれが取ることができる値を知っているいくつかの高水準のオブジェクトではありません。コンパイラは実際にfoo [3]を過ぎた次のメモリ位置を指しているかどうかを知る方法がありませんでした。他の場所でもありません。任意の値をポインタに割り当てることができます。それが何を指しているかは、あなたの責任です。 –

+2

clang 3.9.0は​​、両方の場合について警告します。 IMOそれはコンパイラのバグです。なぜなら、 'bar'は3つのポインタの配列であり、' foo'は3つの 'int'sの配列です。 –

+3

@MichaelWalz' bar'は3の 'int'の配列へのポインタです。 3ポインタの配列。 – mch

答えて

6

fooへのアクセスについては、barのアクセスに関する警告が表示されますので、同じ警告を2度表示しないようにしてください。gcc

別の問題と同じ警告として分類する必要があるかどうか - 一方では異なるタイプの変数が2つありますが、他方では同じメモリに別名を付ける方法を見てください。しかし、それは私にとってかなり合理的なようです。最悪のシナリオでは、両方を修正するまで追加のコンパイルを行います。

int foo[3] = {1,2,3}; 
int (*bar)[3]; 

int main() 
{ 
    bar = &foo; 
    // foo[42] = 42; 
    (*bar)[42] = 42; // warning 
    return 0; 
} 

20 : warning: array subscript is above array bounds [-Warray-bounds] 
(*bar)[42] = 42; 
~~~~~~~~~^ 
0

ポインタにはサイズ情報が格納されていないため、コンパイラには範囲外アクセスが検出されません。

+1

間違っていると、 'bar'は3つのポインタの配列です。 BTW clang 3.9.0は​​、ここで両方のケースについて警告します。 –

+0

@MichaelWalzあなたが正しいです、私の知識は少し錆びていて、私はその定義を誤解しました。しかし、その場合、gccが2番目の範囲外アクセスを報告できないという手掛かりはありますか? – erdeszt

+2

@Michael - 'bar'はintの配列[3]へのポインタです。宣言を読むことができない場合は、 'bar =&foo'を考えてください。これはあなたの解釈の誤りでしょう。 –

0

あなたがbar内の要素の数を変更した場合、それはbar=&fooで互換性のない型に文句を言うだろうにもかかわらず、GCCはへのポインタの配列のサイズ情報を保持し、使用していないことが表示されます:

int foo[3] = {1,2,3}; 
int (*bar)[4]; 

int main(void) { 
    bar = &foo; 
} 
39893471.c: In function ‘main’: 
39893471.c:5:9: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types] 
    bar = &foo; 
     ^

GCCバージョン4.8および6.1でこの動作を確認しました。

N.B. -Warray-boundsが機能するには、-O2引数が必要です。これはしばらく私を捕まえた!

+0

あなたの馬はバグレポートに載せます。私の答えを見てください。 – bolov

1

いくつかの実験の後で、両方の警告が両方のfooとbarの両方の配列インデックスが同じ場合にのみ表示されないことがわかりました。 インデックスを異なる値に変更すると、すべての警告が表示されるようです。以下のfoo1とbar1は、fooとbarのように定義されています。バーがfooを指している、とgccがすでに同じアドレスに対して警告を示したように

bar = &foo; 
bar1 = &foo1; 
foo[10] = NOPE; 
(*bar)[10] = NOPE; 
(*bar1)[11] = NOPE; 
foo1[12] = NOPE; 

は、それがインデックスが同じであれば、バーのために同じ警告を表示するには気にしません。およびその逆。ここで、foo、bar1、foo1の警告が表示され、barは表示されません。

これは考えられる説明でした。

+0

あなたは実際何が起こっているのか把握しています。私はちょうどあなたの理想をとって、より明確かつ簡単な方法で言い換えました。 – bolov

関連する問題