電子書籍の厳選無料作品が豊富!

C/C++におけるPostfix incrementとPrefix incrementの質問です.僕は今まで現在の行のプロセスが始まる前に計算されるのが++aで現在の行のプロセスが終わってから計算されるのがa++だと思っていたのですが違うようです.例えば以下のコードを書いてみました.

bool print(int counter)
{
cout << counter << endl;
return true;
}

int main()
{
int counter = 0;
if(print(counter) && counter++ > 0 && print(counter)){
cout << counter << endl;
}

return 0;
}

この場合出力は
0
です.最初のprintに渡される0が出力されて,counter++ > 0の段階ではcounterは0として比較されるようです.この条件が偽なので2回めのprintは呼ばれないですし,ifの中身も呼ばれないです.

次にcounterの初期値を1にします.

bool print(int counter)
{
cout << counter << endl;
return true;
}

int main()
{
int counter =1;
if(print(counter) && counter++ > 0 && print(counter)){
cout << counter << endl;
}

return 0;
}

この場合の出力は
1
2
2
です.最初のprintに渡されるのは1で,counter++ > 0は1>0で真.2個めのprintには2が渡されて,ifの中身のcounterも2ということだと思います.この2つの実験を合わせると

counter++ > 0の処理の時はまだインクリメントされていないが,
counter++ > 0 && print(counter)の処理の時にはprint(counter)のcounterはインクリメント済みということになると思います.同じ行での処理なので僕の今までの理解では説明できません.C言語のオペレーターの処理順序で説明できるかと思ったのですがそうではなさそうです.http://www.difranco.net/compsci/C_Operator_Prece …

こういう処理がどういう順番で行われるかの細かい定義が知りたいです.今回の例だけでなくインクリメントの処理全体を理解したいです.リンクなどがあればそういったものでも構いません.このサイトでもインクリメントに関する質問はされていますが,今回の例は説明できない気がします(https://oshiete.goo.ne.jp/qa/4753046.html)(あるいは僕が理解できていないのでしょうか?)

解答お持ちしております.

A 回答 (3件)

・前置インクリメントは、インクリメントされた値が使われる


x= ++a ;
を等価なプログラムにするなら
a=a+1 ;
a_temp = a;
x=a_temp;
または
a_temp = a+1;
x=a_temp;
a=a+1 ;
どちらになるかは、規格では決まっていない。

・後置インクリメントは、インクリメントされる前の値が使われる
x= a ++ ;
を等価なプログラムにするなら
a_temp = a;
x=a_temp;
a=a+1 ;
または
a_temp = a;
a=a+1 ;
x=a_temp;
どちらになるかは、規格では決まっていない。


・ && は、左から順番に評価される。
 左が「偽」なら、右は評価されない。(このとき 値0 ( 偽) となる)
if( ex1 && ex2 ) { doSomething ; }
を等価なプログラムに変えるなら次のような感じ
if (ex1) {f=true;} else {f=false;}
if ( f ) {
if (ex2) {f=true;} else {f=false;}
}
if (f) { doSomething;}


・変数の値が変化するような「副作用」は「副作用完了点」までに完了することになっている。
https://oshiete.goo.ne.jp/qa/4132534.html


おそらく、あなたが「現在の行のプロセスが始まる前/終わってから」と言っているのは、この「副作用完了点」を誤解した(あるいは理解が不十分な)ものでしょう。

counter++ > 0 && print(counter)
は次のようになります。
・ && は 左から順番に評価されます
・ 先に評価される counter++ > 0 は、インクリメント前のcounterの値で > 0 の比較が行われます。
・ && は 副作用完了点 なので、右の print(counter)を評価する前に(左が偽の場合は評価せずに) counter=counter+1 は完了しています。
    • good
    • 0
この回答へのお礼

ありがとうございます.

言われた通り副作用(side effect), 副作用完了点(sequence point)について調べなおしてみました.完全に誤解していたようです.

関数呼び出し演算子の(),&&,||,?,コンマはsequence pointであることから,counterのインクリメントは&&より先に完了している,ということで説明ができるということになると思います.ありがとうございました.

お礼日時:2017/01/22 11:15

> So in the statement y = x * z++; the current value of z is used to evaluate the expression


> (i.e., z++ evaluates to z)
> and z only incremented after all else is done.


ご質問の場合
print(counter) && counter++ > 0 && print(counter) の構造は

expression && expression && expressionとなるので

(counter++ > 0) は、
(counter > 0)を評価して、その後counterがインクリメントされる
となるのではないでしょうか。
    • good
    • 0
この回答へのお礼

ありがとうございます.確かにexpression(式)を使った説明でも順序は規定済みのようですね.

JIS X 3010-1993(ISO/IEC 9899/1990) 
構文で示されているか(35)、又は(関数呼出し演算子()、&&、||、?:及びコンマ演算子に対して)後で規定する場合を除いて、部分式の評価順序及び副作用が生じる順序は未規定とする。

つまり&&で挟まれているとその前後で副作用が生じないことは規定済み.この説明も僕が求めていた答えなのですが,No.3さんの説明の方が分かりやすく今後の人の参考にもなるかと思うのでベストアンサーはNo.3さんに渡します.ありがとうございました.

お礼日時:2017/01/22 11:09

>プロセスが始まる前に計算されるのが++aで現在の行のプロセスが終わってから計算されるのがa++だと思っていたのですが違うようです


「現在の行」の意味が不明ですが、
a=1のとき
 a++ は 1
 ++a は 2
ですよ。

>同じ行での処理なので僕の今までの理解では説明できません.
どこが理解できないのでしょうか?

評価されるときのcounterの値を順番に見ていけば
if(print(counter)   0 1
&& counter++ > 0  0 1
&& print(counter)){  x 2
cout << counter << endl; x 2

になりませんか?
    • good
    • 0
この回答へのお礼

ありがとうございます.

現在の行は”;”で区切られるまでの表現の意でした.

今回は>は++よりも先に処理されていますが,&&は++の後に処理されていますよね.これがどこで定義されているかが知りたかったんです.

お礼日時:2017/01/22 11:02

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!