2

複数の条件が C/C++ でどのように処理されるか知りたいです。正常に動作するコードがいくつかありますが、運の要素が関係しているのではないかと心配しており、巻き込まれたくありません。検討:

if ( (/*condition1*/) || (/*condition containing invalid reference*/) )
{
    // do something
}

「条件 1」が TRUE である限り、2 番目の条件自体がエラーを生成する場合でも、2 番目の条件がエラーを生成するようには見えません。例えば:

int main()
{
    char    string1[] = "StackOverflow";
    char    *string2 = 0;

    // (1) This will work because string1 is valid
    if (strlen(string1) != 0)
        printf("%s", string1);

    // (2) This will cause an error
    if (strlen(string2) != 0)
        printf("%s", string2);

    // (3) But this if(OR) works fine
    if ((strlen(string1) != 0)||(strlen(string2) != 0))
        printf("no problem!");

    // (4) And of course this doesn't
    if ((strlen(string2) != 0)||(strlen(string1) != 0))
        printf("I don't believe it!");

    return 0;
}

OR 条件のリストで見ることができます。if() の「質問」は、最初の TRUE ステートメントで停止し、その後に何が続くかに関係なく、左から右に読み取られます。ただし、番号 (3) を次のように変更します。

if ((strlen(string1) == 0) && (strlen(string2) == 0)

最初の条件が false であっても失敗するため、すべてが false になります。つまり、OR の例のように質問が停止しません。

一般化するために、私は次のことを観察しました。

if ( (TRUE) or (INVALID) )   -> no problem

if ( (FALSE) or (INVALID) )  -> error

if ( (TRUE) and (INVALID) )  -> error

if ( (FALSE) and (INVALID) ) -> error    // see the EDIT

これらの結果はすべての場合に普遍的ですか、それともコンパイラ/プラットフォームに依存しますか?

上記のルールに従ってコードを書くことで問題を解決できますか? または、条件の 1 つが無効になるような状況に決して陥らないようにする必要がありますか?

私は上司のためにいくつかの古いコードを調べていますが、上記の (3) のような例が散らばっています。それらをすべてキャッチし、コードを適応させて無効な状態を回避するには、かなりの時間がかかります。(3) と (4) はif(string2 != 0) { // }ブロック内に収まるように簡単に調整できますが、実際には、私が持っているコードではそれほど簡単ではありません。

編集:

再度チェックしてから、if ( (FALSE) and (INVALID) )実際にエラーなしで実行されます。以前に失敗した理由はわかりません。最初にうまくいっていたら、私はその質問さえ提起しなかったかもしれません。魔術と集中力の低さのせいにしよう。

最終的に、答えはほのめかされていますが、逐語的に確認されていませんが、この短絡評価への依存 (wiki リンクに感謝します!) は正当な手法のようです。コードを書き直す必要がないのはうれしいです!

4

4 に答える 4

2

What you are talking about is called "short circuiting" and it is a universal feature in c++. The way it works is (TRUE || anything ) is always going to be true so the expression is not further evaluated once it knows it will be true. The same applies (FALSE && anything), because this will always be false.

a good example of how this is useful:

int x = 0;
cin >> x;
if (x != 0 && 10 / x == 2) {
    // ...
}

With this check on x, if the user enters 0, 10 / 0 will not occur, thus saving your program from dividing by 0.

You can always rely on this feature with expressions involving && and ||

于 2013-02-23T20:40:50.213 に答える
2

はい、これはよく知られた動作であり、標準に準拠するすべての C/C++ コンパイラで機能します。Jesse が彼のコメントで既に述べたように、これは短絡と呼ばれ、特にポインターでかなり頻繁に使用されます。

void func( int *ptr )
{
   if( ptr && *ptr ) {
      // pointer is valid and integer that it points to is not 0
   }
}

あなたの最後の発言:

if ( (FALSE) and (INVALID) ) -> error

正しくありません。別名 && は、左が false の場合、右のオペランドを評価しません。

于 2013-02-23T20:35:09.887 に答える
0
    if (strlen(string2) != 0)
    printf("%s", string2);

ここstring2は文字列ではないため、strlen呼び出しは未定義の動作を呼び出します。

if ((strlen(string1) != 0)||(strlen(string2) != 0))

Cでは、||演算子は、左のオペランドが。と評価された場合、右のオペランドを評価しないことが保証されてい1ます。そして、ここでは、未定義の動作であるsoに||評価されるの左側のオペランドが呼び出されることはありません。1strlen(string2)

于 2013-02-23T20:28:23.307 に答える
0

C と C++ の両方で、結果が確実になるとすぐにブール式の評価を停止します。したがって、演算子は、何かが true を返すとすぐに評価を停止し、左側の部分が優先されます。 && は、何かが false を返すとすぐに停止します。

評価されないように、必要なものを右側に配置できます。

「無効な」式として未定義の動作を使用したことを覚えておいてください。それが機能したとしても、何が起こるかを知る方法はありません。

于 2013-02-23T20:35:09.560 に答える