日々の記録。

プログラミングのメモや感じた事などを記録。

C++講座 その5 サイズとバイトオーダー

サイズ

32bit CPUでWindows系の環境では各型は次のようなサイズになっている。

型名 サイズ(byte)
char 1
short 2
int 4
long 4
float 4?(後日確認)
double 8

「一般的な」としたのは、これらのサイズはCPUやOSの環境に依存するため。64bit環境では上表とは異なる値になる。

C++言語により規定されているのは、次のルールのみで「intはNバイト」という規定はない。

1sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
1 <= sizeof(bool) <= sizeof(long)
sizeof(char) <= sizeof(wchar_t) <= sizeof(long)
sizeof(float) <= sizeof(double) <= sizeof(long double)
sizeof(N) ≡ sizeof(signed N) <= sizeof(unsigned N) // Nはchar,short,int,longのいずれか

C/C++での最大値・最小値の定義

limitsヘッダに各型の最大値、最小値の定数値が定義されている。

#include<limits>
#include<iostream>
using namespace std;

#define cout_limit(T) cout << #T << "," << sizeof(T) << "," << numeric_limits<T>::min() << "," << numeric_limits<T>::max() << endl

int main() {
  cout_limit(bool);
  cout_limit(char);
  cout_limit(short);
  cout_limit(int);
  cout_limit(long);
  cout_limit(float);
  cout_limit(double);
  cout_limit(long double);
  return 0;
}

バイトオーダー

short以上の2バイト以上の型の場合、CPUによって値の配置順序が異なる。

トルエンディアン

Intel系のCPUの場合、リトルエンディアンという順序で値は配置され、次のようになる。

short a = 0;

aが0x1000番地に配置されたと仮定すると、次のように値は設定される。

アドレス
0x1000 0
0x1001 0

a = 1;

アドレス
0x1000 1
0x1001 0

a=255;

アドレス
0x1000 FF
0x1001 0

a = 256;

アドレス
0x1000 0
0x1001 1

これは16進数でメモリをダンプ出力した際、見た目と逆に表示される。(左の桁の方が小さい)

ダンプ(16進数)
0 00 00
1 01 00
255 FF 00
256 00 01

ビッグエンディアン

SH2,SH4や今はなきサンマイクロシステムズのSPARCで採用されている。 リトルエンディアンとは逆順に値が設定される。

short a = 0;

aが0x1000番地に配置されたと仮定すると、次のように値は設定される。

アドレス
0x1000 0
0x1001 0

a = 1;

アドレス
0x1000 0
0x1001 1

a=255;

アドレス
0x1000 0
0x1001 FF

a = 256;

アドレス
0x1000 1
0x1001 0

こちらは16進数でメモリをダンプ出力した際、見た目通りに表示される。(右の桁の方が小さい)

ダンプ(16進数)
0 00 00
1 00 01
255 00 FF
256 01 00

移植性とネットワークバイトオーダー

同じ環境のみでデータを授受している場合、バイトオーダーは問題ない(送信元、受信先ともに同じバイトオーダーのため)。しかし、バイトオーダーの異なる環境で授受する場合は、どちらかに統一する必要がある。例えばTCP/IPの場合、一般的にビッグエンディアン(ネットワークバイトオーダー)に合わせる。 参考 Wikipedia エンディアン

2014/2/15 補足

エンディアンはバイトのみならず、ビットにも存在する。これもCPU等の環境により異なるので移植の際に問題となる。

参考 エンディアンについて (ビット編)