C言語入門|10章のまとめ

第10章では、
C言語の中でも特に「難しい」「怖い」「でも本質的」なテーマである
メモリとポインタの正体に正面から向き合ってきました。

ここまで読み進めてきたあなたは、
もう単に文法をなぞる初心者ではありません。

この章で学んだ内容は、

  • なぜ配列が勝手に書き換わるのか
  • なぜエラーが出ないのに壊れるのか
  • なぜC言語は自由で、同時に危険なのか

といった疑問に、
すべて筋の通った説明を与えてくれる知識です。

このまとめでは、第10章で登場した重要な考え方を
一度きれいに整理して振り返っていきましょう。

特殊構文が見せていた「C言語の素顔」

第10章の前半で学んだ最大のテーマは、
いわゆる 特殊構文 でした。

これは暗記しなければならないルールであると同時に、
C言語の思想そのものでもあります。

配列は引数になるとポインタに化ける

関数の引数や戻り値に配列型を指定すると、
C言語では自動的に ポインタ型として解釈されます。

void func(int a[3]);

この宣言は、実質的に次と同じ意味になります。

void func(int* a);

ここから、

  • 配列を渡したつもりでも
  • 実際にはアドレスを渡している

という事実が導かれます。

配列変数名は「値」ではなく「アドレス」

ソースコード中に配列変数名を書くと、
それは配列そのものではなく、

先頭要素のアドレス

として評価されます。

int a[4];
func(a);

この a は、
a[0] のアドレスに化けて関数へ渡されていました。

添え字演算子の正体

[] 演算子は、
「配列専用の特別な文法」ではありません。

本質的には、

  • 指定されたアドレスを基準に
  • N 個分だけ後ろの場所にある
  • 変数を生み出す

という、純粋なメモリアクセス演算子です。

その結果、

p[n]

*(p + n)

は、常に同じ意味になります。

ポインタ演算が示す「型の重要性」

第10章では、
ポインタ演算についても詳しく学びました。

ポインタ演算の基本ルール

ある x 型のポインタ変数に対して加算や減算を行うと、

sizeof(x) の倍数でアドレスが増減する

というルールが適用されます。

たとえば、

  • int 型なら 4 バイト単位
  • short 型なら 2 バイト単位

で移動します。

この仕組みがあるからこそ、

  • p[n]
  • *(p + n)

が、正しい要素アクセスとして成立していました。

メモリアクセスのための標準関数

第10章の中盤では、
メモリを直接扱うための標準関数を学びました。

これらはすべて、

  • ポインタ
  • メモリアドレス
  • バイト単位の操作

を前提とした、C言語らしい関数です。

memcpy ― メモリをまるごとコピーする

memcpy を使うことで、

  • 配列
  • 構造体
  • 任意のメモリ領域

を、バイト単位で丸ごとコピーできます。

配列を = で代入してはいけなかった理由も、
この章で明確になりました。

memcmp ― メモリをまるごと比較する

memcmp は、

  • 2つのメモリ領域の内容が
  • 完全に一致しているか

を判定する関数です。

配列同士の等価判定は、

  • == 演算子ではなく
  • memcmp を使う

という判断基準が、ここで確立されました。

memset ― メモリを一気に初期化する

memset は、

  • 指定したメモリ領域を
  • 任意の 1 バイト値で
  • まとめて埋める

ための関数です。

0 での初期化によく使われ、
ヒープ利用とも密接に関係します。

配列の限界とヒープという選択肢

第10章の後半では、
「普通の配列」が抱える限界を確認しました。

スタック上の配列の限界

問題内容
サイズ大きな領域を確保できない。
寿命関数終了とともに消える。

この問題を解決するために登場したのが、
ヒープ領域 です。

malloc と free による動的メモリ管理

ヒープ領域は、

  • 実行中に
  • 必要なサイズを
  • 必要なタイミングで

確保できる柔軟なメモリ領域です。

malloc の役割

malloc 関数を使うことで、
ヒープに連続したメモリ領域を確保できます。

void* malloc(size_t len);

free の重要性

ヒープ領域は自動では解放されません。

そのため、

malloc を使ったら、必ず free を呼ぶ

というルールが成立します。

これを守らないと、

  • メモリリーク
  • 長時間実行時の異常終了

といった問題につながります。

第10章を通して身につけてほしい感覚

この章で一番大切なのは、
次の意識です。

C言語では
メモリは「見えないが確実に存在する」
そして
すべての責任はプログラマにある

エラーが出ないから安全なのではなく、
理解しているから安全なのです。

次の章へ向けて

第10章で学んだ内容は、
C言語の中核であり、避けて通れない部分です。

ここをしっかり理解できたあなたは、
もう「なんとなく動くコード」を書く段階を抜けています。

次の章では、
この知識を土台として、
より実践的なプログラムへ進んでいきましょう。