答えは「いいえ」だと思いますが、コンパイラの観点からは、その理由がわかりません。
私は非常に単純なコードを作成しましたが、これはコンパイラの診断をかなりひどく狂わせます (clang と gcc の両方)。これらはコンパイラのバグではないことを指摘しておく必要があります。出力はすべての場合に正しいですが、警告については疑問があります。
次のコードを検討してください。
#include <iostream>
int main(){
int b,a;
b = 3;
b == 3 ? a = 1 : b = 2;
b == 2 ? a = 2 : b = 1;
a = a;
std::cerr << a << std::endl;
}
の割り当てa
はトートロジーです。これa
は、 が に関係なく、2 つの 3 項ステートメントの後に初期化されることを意味しb
ます。GCC はこのコードに完全に満足しています。Clang は少し賢く、ばかげたこと ( warning: explicitly assigning a variable of type 'int' to itself [-Wself-assign]
) を見つけますが、大したことではありません。
これで (少なくとも意味的には) 同じことですが、構文が短くなります。
#include <iostream>
int main(){
int b,a = (b=3,
b == 3 ? a = 1 : b = 2,
b == 2 ? a = 2 : b = 1,
a);
std::cerr << a << std::endl;
}
現在、コンパイラはまったく異なる警告を表示します。Clang はもはや奇妙なことを報告しません (これは、括弧の優先順位のため、おそらく正しいでしょう)。gcc はもう少し恐ろしく、次のように述べています。
test.cpp: In function ‘int main()’:
test.cpp:7:15: warning: operation on ‘a’ may be undefined [-Wsequence-point]
しかし、それは本当ですか?このシーケンス ポイントの警告は、コンマ区切りのステートメントが実際には同じように処理されないというヒントを与えてくれますが、そうすべきかどうかはわかりません。
そして、コードを次のように変更すると、さらに奇妙になります。
#include <iostream>
int main(){
int b,a = (b=3,
b == 3 ? a = 1 : b = 2,
b == 2 ? a = 2 : b = 1,
a+0); // <- i just changed this line
std::cerr << a << std::endl;
}
そして突然、clang は何か怪しいものがあるかもしれないことに気付きましたa
:
test.cpp:7:14: warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]
a+0);
^
しかし、以前は問題がありませんでしたa
...いくつかの理由で、この場合、clang はトートロジーを見つけることができません。繰り返しますが、それは単に、それらが完全なステートメントではないためかもしれません。
問題は次のとおりです。
- このコードは有効で、適切に定義されていますか (すべてのバージョンで)?
- コンマ区切りのステートメントのリストはどのように処理されますか? 明示的なステートメントを含むコードの最初のバージョンとは異なる必要がありますか?
- GCC は未定義の動作とシーケンス ポイントの問題を報告する権利がありますか? (この場合、clang にはいくつかの重要な診断が欠けています) may と表示されていることは承知していますが、それでも...
a
最後のケースで初期化されていない可能性があると報告するのはclangの権利ですか? (その後、前のケースと同じ診断が必要です)
編集とコメント:
- このコードは単純ではないという (正当な) コメントがいくつか寄せられています。これは事実ですが、ポイントは、初期化子でコンマ区切りのステートメントに遭遇すると、コンパイラが誤診することです。これは悪いことです。「この構文を試してみました...」というコメントを避けるために、コードをより完全なものにしました。より現実的で人間が読める問題のバージョンを書くこともできますが、それは間違った診断を示しますが、このバージョンはより多くの情報を示し、より完全であると思います。
- コンパイラ拷問テストスイートでは、これは非常に理解しやすく読みやすいと考えられますが、はるかに悪いことをします:) コンパイラをテストして評価するには、そのようなコードが必要です。これは製品コードでは見栄えがよくありませんが、ここでのポイントではありません。