いきなりですが問題です.
int i; for (i = 8; i > 0; i /* */ 1) printf("%d", i);
「8421」と出力するためには,「/* */」のところに何を書けばよいですか.
月曜に実施した試験の改題です.さっそくですが解答をすると,「>>=」です.右シフトの複合代入演算子で,i >>= 1はi = i >> 1と同じであり,その時点のiの値を右に1ビット,シフトして,その結果をiに代入しなさいという指示になります.
残念ながら正解率は,予想よりも低くなりました.「>>」とする答案が目立ちます.これでは,i >> 1となってiの値が更新されず,「8888…」と無限に出力されます.
これで終わったら,当ブログで取り上げることもありませんで,別解がいくつかあります.まず当然ながら,「= i >>」も正解となります.
問題作成の際には,除算演算子の「/」や,その複合代入演算子「/=」を使った答案があるかもしれないと考えました.とはいえ単純に演算子を置く,「i / 1」も「i /= 1」も,iの値は変更されません.
SQLインジェクションをヒントにして,思い浮かんだのは「/=2,」です.当てはめると「i /= 2, 1」となります.カンマ演算子を使って,出題にある1を実質的に無視するという考え方です.こんな答えを書く学生はいないだろうけど,解答・解説では挙げておこうかな…
試験を終え,蓋を開けてみますと,頑張ったコードがいくつかありました.複数の学生が,「=i-i/2*」と解答していました.当てはめると,「i = i - i / 2 * 1」となって,なるほど,こういう1の無力化もあり得るなあ,出力は「8421」だ…
いやいや,これはまずいです.iが1のときの更新式は,「i = 1 - 1 / 2 * 1」で,“整数/整数は整数”に注意すると,「1 / 2」が0に評価されますので,結局「i = 1」です.最後の最後だけ,iの値が変化せず,出力は「8421111…」となります.
他学科でCプログラミングの授業をお持ちの先生に,この出題を示すと,うちのところではシフト演算子を扱っていないんだけどとおっしゃたのち,「/=1+」を挙げてくださいました.更新の式は「i /= 1 + 1」です.これは簡潔明瞭な別解でした.