Edited at

Twitterで話題のC++ quiz time!の解説を誰も書かないので書く


問題

こんなツイートが人気を博していた。

#include <iostream>

#include "typename.h"
int main()
{
short a = 1;
std::cout << sizeof(+a)["23456"] << std::endl;
}

答えは四択で1,3,4,6のどれですか?というもの。

だれか解説書くだろと思ったが、みんなTwitter上で満足してしまったらしい(見落としてたらすまん)。解説するか。


正解

1になります。

・・・えええっ!?

(私は6だと騙された)


6と誤答した人の脳内回路

誤答したの私だ。アンケートを見ても一番多い。

江添さんがノリノリで誤答を書き込んでいる。

sizeof(+a)["23456"]をどうパースしたかというと


  1. +a

  2. sizeof(+a)

  3. sizeof(+a)["23456"]

とパースしてしまったのだと思う。一般にsizeof演算子は必ず()とつけて使いましょう、と多くの初心者本にかかれており、そして実際多くのC++erが()をつけて使うもんだから、うっかりsizeof(+a)とパースしてしまいそうになるが、operator[]の優先順位がめっちゃ高いことを忘れないでほしい(ブーメラン)


  1. 暗黙変換でintになるよね~

  2. sizeof取ったら4でしょ?


  3. a[b]b[a]とも書けるから文字列の4番めの要素は6

と考えていく。

不正解だ


4と誤答した人の脳内回路

6とほぼ同じだが+aが暗黙変換でintになることを見落とすと4になる


  1. shortでしょ?

  2. sizeof取ったら2でしょ?


  3. a[b]b[a]とも書けるから文字列の4番めの要素は4

と考えていく。

不正解だ


3と誤答した人の脳内回路

ごめんなさい、さっぱりわからない。アンケートでももっとも票数が少ないものの、殆ど無いってわけでもないくらい投票されている。

short a = 1;

だからよくわからんけど文字列の1番めの要素を見に行ってしまったとか??


解説


+a

改めて見ていこう。

short a = 1;

なのでaの型はshort型だ。では+aの型は?

実はint型になる。

単項演算子+の演算の際にintegral promotionという暗黙変換が行われるためだ。

まあ実はint型であるかは重要ではない


(+a)["23456"]

そうだ、ここで誤ってsizeof(+a)を考えてしまうと誤りだ。

operator[]はポインタ演算*(a + b)のsyntax sugarであるというのは割と有名な小話だと思う。

int arr[3] = { 1, 2, 3 };

arr[1]; // => 2
1[arr]; // => 2
*(arr + 1); // => 2

つまりこの場合

(+a)["23456"]"23456"[+a]は等価だ。

aの値は

short a = 1;

より1なので演算結果はchar型の3になる。


sizeof(+a)["23456"]

ようやくsizeof演算子の出番だ。(+a)["23456"]はchar型なので、sizeofを取ると1になる。

sizeof((+a)["23456"])となっていれば引っかかる人は少なかっただろうが・・・。


余談

@Chironian 氏御用達の型名を表示させるマクロTYPENAMEを使いつつ、問題のコードをいじると理解度が増すかもしれない。

#include <iostream>

#include "typename.h"
int main()
{
short a = 1;
std::cout
<< sizeof(+a) << std::endl
<< "23456"[4] << std::endl
<< 4["23456"] << std::endl
<< (+a)["23456"] << std::endl
<< TYPENAME((+a)["23456"]) << std::endl
<< sizeof(+a)["23456"] << std::endl;
}

https://wandbox.org/permlink/TT51W7xs3ZEfKpeq


実行結果

4

6
6
3
char
1


教訓



  • sizeof演算子を使うときは()でくくりましょう


  • operator[]の優先順位の高さを忘れない


感想

まんまとひっかかった、くやしい。


License

CC BY 4.0

CC-BY icon.svg