クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

C言語の変数のサイズとメモリ

このレッスンのあとで: 変数の大きさと、メモリのどこにあるかを言える。

50分のレッスンコマンド4件コンパイラとアーキテクチャのラボ:gcc、flex、bison、RISC-V を1台の VM で

メモリは番号の付いたバイトの列

C言語の変数は、メモリの中で決まった大きさと場所を持ちます。メモリは、番号の付いた1バイトずつの箱が、ずらりと並んだものです。

この番号を番地(アドレス)と呼びます。変数の大きさと番地が分かると、プログラムが何バイト使うかが読めます。構造体が、メンバーの合計より大きくなる理由も分かります。

このレッスンのゴール

メモ

変数の大きさと、メモリのどこにあるかを言える。

重要な言葉

ことばいみれい
バイトメモリの箱1つ。0から255までの数が入る
番地バイトに付いた番号。アドレスとも言う
型変数が何バイトで、どう読むかを決めるものint
アライメント変数を置ける番地の決まり。大きさの倍数の番地
パディングアライメントのために入れる、使わない空きバイト
構造体いくつかの変数を1つにまとめたものstruct

学生が入力するセルは、このプレビューでは空白です。

型が変数のバイト数を決める

C言語では、型が変数のバイト数を決めます。char は1バイト、short は2バイト、int は4バイト、double は8バイトです。

sizeof という演算子は、型や変数の大きさをバイト数で返します。この数は、64ビットの Linux なら、どの機種でも同じです。

型と大きさの一覧

型バイト数入れるもの
char11文字、小さな整数
short2小さめの整数
int4ふつうの整数
long8大きな整数
double8小数
ポインタ8番地

学生が入力するセルは、このプレビューでは空白です。

4つの型の大きさ

コマンド
printf '%s\n' 'int main(void){printf("%zu %zu %zu %zu\n", sizeof(char), sizeof(short), sizeof(int), sizeof(double)); return 0;}' | gcc -include stdio.h -x c - -o /tmp/sizes && /tmp/sizes

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

long とポインタの大きさ

コマンド
printf '%s\n' 'int main(void){printf("%zu %zu\n", sizeof(long), sizeof(void *)); return 0;}' | gcc -include stdio.h -x c - -o /tmp/wide && /tmp/wide

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

変数は大きさの倍数の番地に置かれる

int は4バイトなので、4の倍数の番地に置かれます。0、4、8、12 の番地は使えますが、番地6は使えません。この決まりがアライメントです。

char のあとに int を置くと、間の3バイトが空きます。この空きがパディングです。メンバーの合計より、構造体が大きくなる理由です。

3つのメンバーを持つ構造体

コード: c
struct a {
    char x;   /* 1バイト */
    int y;    /* 4バイト */
    char z;   /* 1バイト */
};

12バイトの中身

番地中身使うバイト
0x1
1から3パディング3
4から7y4
8z1
9から11パディング3

学生が入力するセルは、このプレビューでは空白です。

並べ方で大きさが変わる

コマンド
printf '%s\n' 'struct a {char x; int y; char z;}; struct b {int y; char x; char z;}; int main(void){printf("%zu %zu %zu\n", sizeof(struct a), sizeof(struct b), offsetof(struct a, y)); return 0;}' | gcc -include stdio.h -include stddef.h -x c - -o /tmp/pad && /tmp/pad

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

int の番地を4で割った余り

コマンド
printf '%s\n' 'int main(void){int x = 1; printf("%d\n", (int)((size_t)&x % 4)); return 0;}' | gcc -include stdio.h -x c - -o /tmp/al && /tmp/al

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

構造体の大きさは、メンバーの大きさの合計だ、と思いがちです。上の例なら 1 + 4 + 1 で6バイトです。実際は、アライメントのためにパディングが入るので12バイトです。大きさを知りたいときは、いつも sizeof で測ります。

さらに挑戦: 配列の大きさ

課題が通ったら、同じ構造体を10個並べた配列の大きさを考えましょう。1つが12バイトなら、配列は120バイトです。

まず、struct_size を使う array_size(fields, count) を書きます。そして、メンバーを並べ替えると配列がいくつ小さくなるかを、説明しましょう。

このラボとソースについて: コンパイラとアーキテクチャのラボ:gcc、flex、bison、RISC-V を1台の VM で

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。