この質問はインタビューで私に尋ねられましたchar
。OS によっては のサイズが 2 バイトですが、オペレーティング システムによっては 4 バイトまたはそれとは異なります。
どうしてこんなことに?
などの他の基本的なタイプと異なるのはなぜint
ですか?
この質問はインタビューで私に尋ねられましたchar
。OS によっては のサイズが 2 バイトですが、オペレーティング システムによっては 4 バイトまたはそれとは異なります。
どうしてこんなことに?
などの他の基本的なタイプと異なるのはなぜint
ですか?
それはおそらくひっかけ問題でした。は常に1 ですsizeof(char)
。
サイズが異なる場合は、コンパイラが準拠していないことが原因である可能性があります。この場合、C や C++ 言語ではなく、コンパイラ自体について質問する必要があります。
1 sizeof 演算子は、そのオペランドのオブジェクト表現のバイト数を返します。オペランドは、評価されない式か、括弧で囲まれた型 ID です。sizeof 演算子は、関数または不完全な型を持つ式、またはすべての列挙子が宣言される前の列挙型、またはそのような型の括弧で囲まれた名前、またはビットフィールドを指定する左辺値に適用されません。
sizeof(char)
、sizeof(signed char)
およびsizeof(unsigned char)
1 です。その他の基本型 (3.9.1) に適用される sizeof の結果は実装定義です。(私のものを強調)
指摘されたもの以外の型の sizeof は実装定義であり、さまざまな理由で異なります。Anint
は、32 ビットではなく 64 ビットで表された方が範囲が広くなりますが、32 ビット アーキテクチャでは 32 ビットの方が効率的です。
型の物理サイズ (ビット数) は、通常、ターゲット ハードウェアによって決まります。
たとえば、一部の CPU では、16 ビット以上の単位でしかメモリにアクセスできません。最高のパフォーマンスをchar
得るには、16 ビット整数を定義できます。この CPU で 8 ビット文字が必要な場合、コンパイラは、16 ビット メモリ セルとの間で 8 ビット値をパックおよびアンパックするための追加コードを生成する必要があります。その余分なパッキング/アンパッキング コードにより、コードが大きくなり、遅くなります。
そして、それで終わりではありません。16 ビットのメモリ セルを 8 ビットの文字に分割すると、アドレス/ポインタに余分なビットが効果的に導入されます。通常のアドレスが CPU で 16 ビットの場合、この余分な 17 番目のビットをどこに貼り付けますか? 次の 2 つのオプションがあります。
後者のオプションが実用的な場合もあります。たとえば、アドレス空間全体が半分に分割され、そのうちの 1 つがカーネルによって使用され、もう 1 つがユーザー アプリケーションによって使用される場合、アプリケーション ポインターはアドレスで 1 ビットを使用しません。そのビットを使用して、16 ビット メモリ セル内の 8 ビット バイトを選択できます。
C は、できるだけ多くの異なる CPU で実行できるように設計されています。これが、、、、、、、、、、、、、などの物理char
的なサイズが異なる理由です。short
int
long
long long
void*
void(*)()
float
double
long double
wchar_t
ここで、同じ CPU 用のコードを生成するさまざまなコンパイラでさまざまな物理サイズについて話している場合、これはより恣意的な選択になります。ただし、見た目ほど恣意的ではないかもしれません。たとえば、Windows 用の多くのコンパイラでは、int
= long
= 32 ビットが定義されています。INT
これは、 = LONG
= 32 ビットを想定している Windows API を使用する際のプログラマーの混乱を避けるためです。and を別のものとして定義するint
とlong
、プログラマーの注意が失われるため、バグが発生する可能性があります。したがって、コンパイラはこの場合に従う必要があります。
そして最後に、C (および C++) 標準はchars
および で動作しbytes
ます。サイズ的には同じコンセプトです。しかし、C のバイトは典型的な 8 ビット バイトではありません。以前に説明したように、合法的にそれよりも大きくなる可能性があります。混乱を避けるためにoctet
、8 という数字を意味する という用語を使用することができます。多くのプロトコルで、まさにこの目的のためにこの単語が使用されています。