2011-01-08 13 views
12

次のステートメントを考慮してください。 bに格納される値は何ですか?条件付き演算子の使用

int a=1; 
int b = a+=1 ? a+=1 : 10; 

回答は4です

+7

未定義の動作。 – GWW

+1

@GWW:いいえ! [....] –

+3

"誰もそれがどのように働くか説明できますか?" >>私は確かにそれを書いたプログラマーに尋ねることはできません。もう一度何かを書くように彼に依頼しないでください。 :) – Mehrdad

答えて

14

これは優先順位と関係しています。あなたは(簡単にするために変更され、右端のa+=1と)次のコードを調べる場合:

#include <iostream> 

int main (void) { 
    int a=1; 
    int b = a+=1 ? 7 : 10; 
    std::cout << b << std::endl; 
    return 0; 
} 

あなたは出力が8、ない7または10であることがわかります。

int b = (a += (1 ? a += 1 : 10)); 

と、順番にを:あなたのケースに、我々が得ることに加え、

int b = (a += (1 ? 7 : 10)); 

int b = a+=1 ? 7 : 10; 

として解釈されている:文だから

の実行:

  • 右端a += 11がtrue)は、a2と設定されています。
  • 左端a += 22は前の手順の結果です)a4を設定します。
  • b = 44は前の手順の結果です)。

必ずしもその評価の順序に頼ることはできません。 ?にシーケンスポイントが存在しても(続行する前に1が完全に評価されるため)、右端のa += ...と最も左のa += ...の間にシーケンスポイントはありません。

warning: operation on ‘a’ may be undefined 

それはあなたの4を与えているという事実は、純粋な偶然の一致であること:そして、介在配列ポイントなしで二回、単一の変数を変更するとgcc -Wallはあなたに非常に便利なメッセージを与える理由である、未定義の動作です。これは、同じように簡単に65535、あなたに3を与えたり、あなたに

+0

@shreedhar:はい私のコメントを削除しました。この回答は正しいと思われます。 –

+0

BTW g ++では、「aの操作が定義されていない可能性があります」という警告が表示されます。 –

+1

@Prasoon:それは 'a + = a + = 1'が定義されていないからです。 – ephemient

2

アセンブリ解析:-)レッスンを教えるために、あなたのハードディスクをフォーマットすることができます:上記のコードのために(MinGWのを使用して)生成

int main() 
{ 
    int a=1; 
    int b = a+=1 ? a+=1 : 10; 
    return 0; 
} 

アセンブリコードをされます下に示された。コメントはもちろん私のコメントです!コメントも読んでください!

call ___main  //entering into main() 
movl $1, 12(%esp) //int a = 1; means 12(%esp) represents a; 
incl 12(%esp)  //a+=1 ; a becomes 2 
movl 12(%esp), %eax //loading 'a' onto a register(eax); eax becomes 2 
addl %eax, %eax  //adding the register to itself; eax becomes 4 
movl %eax, 12(%esp) //updating 'a' with the value of eax; 'a' becomes 4 
movl 12(%esp), %eax //this step could be optimized away; anyway it loads value of 'a' onto the register(eax); eax becomes 4, in fact even earlier it was 4 too! needless step! 
movl %eax, 8(%esp) //loading the value of eax at another memory location which is 8(%esp); this location represents b; 
movl $0, %eax  //making eax zero! the return value of main()! 
leave    //now main() says, please leave me! 

12(%esp)はつまり、8(%esp)bを表し、aのメモリ位置を表し、そしてそれからの距離4バイトで。 最後に、これらの両方のメモリ位置の値は4です。したがって

、B = 4また= 4

6

これら2つのコードスニペットが原因解析されなければならない方法を化合物式判断Cの文法規則++に相当する他の回答に記載されているとおり。

int a=1; 
int b = a+=1 ? a+=1 : 10; 

int a=1; 
int b = (a += (1 ? (a += 1) : 10)); 

条件式のシーケンス点があるが、それは、最初の式(1)の評価と第二のいずれか一方の評価の間にあると3番目の式が評価されます(この場合はa += 1)。 2番目または3番目の式の評価後に明示的な余分なシーケンスポイントはありません。

これは、コードが未定義の動作を持っているので、aが介在配列ポイントなしbの初期化子で二回修正されていることを意味します。

+0

これは正解です。グッドキャッチチャールズ。 :) +1 –