C++言語でのint型とlong型とlong long型の違いについて


C++において、int型とlong型とlong long型の違いについて教えていただきたいです。  
特に表現できる上限値について知りたくて、調べてみると下記な認識です。

int -> 2^31 - 1  
long -> 2^31 - 1  
long long -> 2^63 - 1

intとlong longの違いはわかるのですが、longの位置付けがよくわからないです。  
longもlong longも2^63 - 1ですし。Atcoderの解説の動画で、intで足りない場合はlong
longを使うといった内容を解説されたのですが、え、intの次っていったらlongじゃないのかな？  
などと疑問に思って調べてみたらなおさらよくわからなくなったという背景です。

longとlong longの違いについて、上限値の観点で説明いただけますと助かります。  
バージョンによるかもしれないので、c++11使ってることも共有しておきます。

よろしくおねがいします。




[c](/questions/tagged/c "'c' のタグが付いた質問を表示") は太古からある言語です。
[c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") は
[c](/questions/tagged/c "'c' のタグが付いた質問を表示") との互換性を重要視している言語なので、この件に関しては事情は
[c](/questions/tagged/c "'c' のタグが付いた質問を表示") と同じです。というあたりを知ってもらった上で

[c](/questions/tagged/c "'c' のタグが付いた質問を表示") は 8bit マイコンでも 16bit
マイコンでも使える言語です。そして `int` は「その処理系で自然な大きさ」を選べるよう、言語規格書上は大きさ（ビット数）を厳密に定めていません。

[c99](/questions/tagged/c99 "'c99' のタグが付いた質問を表示") 言語規格書 ISO/IEC 9899:1999
が定めているのは

  * `char` は 8bit 以上 `int` 以下のサイズであること
  * `int` は 16bit 以上のサイズであること
  * `long` は 32bit 以上 `long long` 以下のサイズであること
  * `long long` は 64bit 以上のサイズであること

今でも組み込み系で当然のように使っている 8/16bit マイコンで先の条件を満たすには

  * `char` 8bit
  * `int` 16bit
  * `long` 32bit

32bit マイコンあるいは x86 等の高級 32bit プロセッサでは同様

  * `char` 8bit
  * `short` 16bit
  * `int` 32bit

では `long` や `long long` を具体的にどの大きさにするかはプロセッサ自体の設計者やコンパイラの設計者や OS
自体の仕様策定者の判断にゆだねられるところです。この判断の基準には

  * よりハードウエアの性能を引き出しやすい (32bit 専用ソースを書きたい)
  * より既存のソフトウエアを移植しやすい (16bit 時代のソースに手を入れたくない）

という相反する面があって、紆余曲折の末、多くの 32bit プロセッサ用コンパイラでは

  * `long` 32bit (16bit 時代のソースコードとの互換性確保のため)
  * `long long` 64bit (`long` より大きい型が必要になったため)

に落ち着いています（ご質問の中に書かれているとおり）。

なのでご質問に対する回答は「昔のソースコードを移植しやすい型サイズを選んだ結果、このサイズが採用されている」となるでしょう。

64bit プロセッサの場合は「既存のソフトウエアとの互換」面が特に重要視されており、型の大きさに関しては異なる仕様が並存しているのが現状です。 LP64
とか LLP64 とか。  
<https://project-
flora.net/2015/07/21/cc%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E6%95%B4%E6%95%B0%E5%9E%8B%E3%81%AB%E3%81%AF%E6%B0%97%E3%82%92%E3%81%A4%E3%81%91%E3%82%88/>

そして型の大きさがコンパイラによって異なるのはすごく不便と言うことで [c99](/questions/tagged/c99 "'c99'
のタグが付いた質問を表示") や [c++11](/questions/tagged/c%2b%2b11 "'c++11' のタグが付いた質問を表示")
では大きさを厳密に定めた型とかが追加されています（上記ページでも解説されています）。移植性を重視するなど型の大きさを気にする必要がある場合は `int` や
`long` といった処理系ごとに大きさが違う可能性のある型を使わずに `int16_t` などを使うことが推奨されています。

