web-dev-qa-db-ja.com

?:1つの式を空のままにした場合の3項条件演算子の動作

試行錯誤しながら数字を「推測」しようとするコンソールアプリケーションを書いていたところ、問題なく動作しましたが、ぼんやりと書いた特定の部分について疑問に思いました。

コードは次のとおりです。

_#include <stdio.h>
#include <stdlib.h>

int main()
{
    int x,i,a,cc;
    for(;;){
    scanf("%d",&x);
    a=50;
    i=100/a;
for(cc=0;;cc++)
{
    if(x<a)
    {
        printf("%d was too big\n",a);
        a=a-((100/(i<<=1))?:1);

    }
    else if (x>a)
    {
        printf("%d was too small\n",a);
        a=a+((100/(i<<=1))?:1);

    }
    else
    {
        printf("%d was the right number\n-----------------%d---------------------\n",a,cc);
        break;
    }
}
}
return 0;
}
_

より具体的に私を混乱させた部分は

_a=a+((100/(i<<=1))?:1); 
//Code, code
a=a-((100/(i<<=1))?:1);
_

_((100/(i<<=1))?:1)_を使用して、100/(i<<=1)が0(またはfalse)を返した場合、式全体が1 _((100/(i<<=1))?:***1***)_と評価されることを確認し、条件の一部を残して、真の空_((100/(i<<=1))? _this space_ :1)_でした。正しく機能しているようですが、条件のその部分を空のままにしておくことにリスクはありますか?

38
TooBored

これはGNU C拡張( ?: wikipedia entry を参照))であるため、移植性のために2番目のオペランドを明示的に記述する必要があります。

'true'の場合、条件付きの結果を返します。

次のステートメントはほぼ同等です。

a = x ?: y;
a = x ? x : y;

唯一の違いは、最初のステートメントにあります。xは常に1回評価されますが、2番目のステートメントでは、xがtrueの場合に2回評価されます。したがって、唯一の違いは、xを評価するときに副作用がある場合です。

いずれにせよ、これは構文の微妙な使用法だと思います...そして、コードを維持している人たちに共感がある場合は、オペランドを明示的に述べる必要があります。 :)

一方、これは一般的なユースケースにとってはちょっとしたトリックです。

59
Stephen

これは GCC拡張 C言語です。 ?:の間に何も表示されない場合、真の場合は比較の値が使用されます。

条件式の中間オペランドは省略できます。次に、最初のオペランドがゼロ以外の場合、その値は条件式の値です。

したがって、式

    x ? : y

それがゼロ以外の場合、xの値を持ちます。それ以外の場合、yの値。

この例は完全に同等です

    x ? x : y

この単純なケースでは、中間オペランドを省略する機能は特に役に立ちません。有用になるのは、最初のオペランドに副作用が含まれている場合、または含まれている可能性がある場合です(マクロ引数の場合)。次に、途中でオペランドを繰り返すと、副作用が2回実行されます。中間オペランドを省略すると、再計算による望ましくない影響なしに、すでに計算された値が使用されます。

20
Matt B.