2017-05-14 13 views
5

-Wsequence-pointを有効にすると、GCCは未定義の動作コードが検出されたときにユーザーに警告する必要があります。例えばこの例でGCCが警告を出さない理由

b = a + ++a; 

は、GCCが注目されるべきであり(ISO Cを添加するためのオペランドを評価する順序を指定していないので)「未定義の動作」コードとして報告されるべきです。

しかし、私は構文で演奏し、私はこの1つ試してみました:

int *a = malloc(sizeof(int) * 2); 
a[0] = 1; 
printf("%d\n", *(a + (*a)++ - *a)); 

もちろん、私は警告

警告ました:「*」不定になることがあります[上の操作を - Wsequence点(a[0]ある)*aの値をインクリメントしてもよいし、一方ではないかもしれないので、私が期待したものである

第3オペランドを処理する。しかし、私は次の1つを試しました:

int *a = malloc(sizeof(int) * 2); 
a[0] = 1; 
printf("%d\n", *(a + (*a)++ - 1)); 

警告が出なかったので私は驚いていました。これもUBではないでしょうか?つまり、ISO C99によれば、ポストインクリメント演算は、式の評価(カンマ演算子と三項演算子を除く)のいずれの時点でも評価できます。後者の例では、ポインタをインクリメントするのではなく、ポインタが指している整数をインクリメントしています。したがって、標準に従えば、それはいつでもインクリメントすることができます(つまり、式全体が評価された後にインクリメントすることができます)ので、プログラムは1または2の両方を印刷することがあります。

なぜGCCは警告をスローしませんか?それとも私は何かが恋しい?私は間違って仕様を理解しましたか?

答えて

6

gccの静的解析ツールはこのような状況に対応していません。 *axが含まれている場合、すなわち、 - それは何らかの非常に特殊な状況下でのシーケンスポイントの不足のため、未定義の動作につながるので

表現*(a + (*a)++ - x)は、GCCの静的解析のためにあまりにも難しいです。これは(*a)++ - xがお互いに「元に戻す」ため、全体の表現が*aといくつかの副作用に相当するようになります。

gccコード解析でこのエラーが発生するようにするには、コンパイラはその有効期間中に*aの内容を追跡する必要があります。あなたの例では単純に見えますが、ユーザー入力からデータがaに読み込まれるより複雑なプログラムは、そのような解析を不可能にします。

関連する問題