C
OS や組み込みを支える低レベル言語。多くの言語の祖となった基礎的存在
C とは
C 言語は、Unix を書くための言語として Bell 研究所の Dennis Ritchie が作った汎用プログラミング言語だ。Ritchie 自身の解説によれば、C が形になったのは 1969 年から 1973 年にかけてで、最も変化が大きかったのは 1972 年だった。型を持たない BCPL から派生した B に型の仕組みを与えたところが出発点にある。ハードウェアに近い低レベルな操作ができながら、人間が読み書きしやすい構文を備える。OS (UNIX/Linux)、組み込み機器、各種言語の処理系など、コンピュータの土台となるソフトウェアの多くが C で書かれている。
C++・Objective-C・Java・C#・Go のように、後から出た多くの言語が中括弧の構文や演算子の書き方を C から引き継いだため、しばしば祖先として語られる。ただし Lisp・Fortran・Smalltalk のように C より前から別系統で発展した言語もあるので、「すべての言語の祖」ではない。影響が大きい系統の起点、という理解が正確だ。
なぜ今も重要か
| 用途 | 理由 |
|---|---|
| OS・カーネル | ハードウェアを直接制御できる |
| 組み込み・IoT | 限られた資源で高速に動く |
| 言語処理系 | 多くの言語が C で実装される |
| 学習 | コンピュータの動作原理が学べる |
メモリやポインタを直接扱うため、コンピュータが内部でどう動くかを理解するのに最適な言語でもある。
規格の系譜と「どの C」で書くか
1978 年に Brian Kernighan と Ritchie が書いた『The C Programming Language』(通称 K&R) が、正式な規格ができるまで 10 年以上のあいだ事実上の言語定義として使われた。規格化は 1983 年夏に発足した ANSI X3J11 委員会が担い、1989 年末にまとまった報告書が最初の公式規格となり、これがそのまま ISO に受け入れられて ISO/IEC 9899-1990 になった。以後は同じ ISO/IEC 9899 の改訂として続いている。
| 版 | 位置づけ |
|---|---|
| K&R (1978 年の書籍) | 規格制定前の事実上の言語定義 |
| ANSI C (1989 年末) | 最初の公式規格・翌年に ISO/IEC 9899-1990 として ISO 化 |
| C99 以降 | ISO/IEC 9899 の改訂として継続 |
| C23 | 最新版・2024 年に ISO と IEC が採択 (規格委員会 WG14 の記述・2026 年 8 月時点) |
注意したいのは、処理系の既定が最新規格とは限らないことだ。Apple clang 21 では、規格を指定せずにコンパイルすると __STDC_VERSION__ は 201710L (C17) を返し、-std=c23 を付けて初めて 202311L になる。どの版で書くのかは必ずコンパイルオプションで明示し、チームと CI で揃えておく。「手元では通るのに別環境で落ちる」の典型的な原因がここにある。
C++ との関係
C++ は C を拡張してオブジェクト指向などを加えた言語で、両者はしばしば比較される。C はシンプルさを保ち、機能を絞ることで小ささと移植性を維持している。一方 C++ は大規模開発向けの高度な機能を持つ。「最小限の制御」を求めるなら C、「制御に加えて大規模な抽象化」を求めるなら C++ という棲み分けになる。
学ぶうえでの注意点
C の自由度は強力だが危険でもある。メモリを手動で管理するため、確保・解放のミスがクラッシュやセキュリティ脆弱性 (バッファオーバーフローなど) に直結する。現代の高水準言語が自動でやってくれることを、C では自分で正しく行う責任がある。だからこそ学ぶ価値が大きく、コンピュータの仕組みを肌で理解する糧になる。実務での新規開発に使うかは、性能・移植性の要件次第で判断したい。
未定義動作という落とし穴
C の危険さは、書き間違いがその場で止まってくれない点にある。規格が結果を定めていない操作 (未定義動作) を書くと、コンパイラは「その状況は起こらない」と仮定して最適化してよい。だから最適化の強さを変えるだけで実行結果が変わる。
#include <stdio.h>
#include <limits.h>
int grows(int x) { return x + 1 > x; }
int main(void) { printf("%d\n", grows(INT_MAX)); return 0; }
符号付き整数のオーバーフローは未定義動作なので、x + 1 > x は桁があふれれば偽になり得るのに、コンパイラは常に真と見なして定数へ畳み込める。Apple clang 21 で試すと -O0 では 0、-O2 では 1 が出力された。同じソースが最適化の指定だけで逆の答えを返す。バグが再現しない、リリースビルドだけ壊れるという厄介な症状はこうして生まれる。
対処は 2 段構えになる。書く側では、あふれないことを先に確かめてから足す (x < INT_MAX を判定してから x + 1 を評価する)。動かす側では検出器を有効にする。-fsanitize=undefined を付けて実行すると、上の例は runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' と発生位置付きで報告される。解放後の参照やバッファ越えは -fsanitize=address が担当し、heap-use-after-free としてアドレスとともに報告される。テストが通ったことを安全の根拠にせず、検出器を通した実行を習慣にしたい。
今から C を選ぶかの判断
新規開発で C を選ぶかは、次の 3 点で切り分けると迷いにくい。
- その環境で他に選択肢があるか。 OS のカーネルや既存のカーネルモジュール、資源の限られたマイコン、他言語から呼ばれる共有ライブラリのように、C の呼び出し規約や実行環境が前提になっている領域では C が最短経路になる。
- メモリ安全性の責任を負う体制があるか。 確保・解放と境界の管理を人が担う以上、検出器付きの継続的なテストとレビューが要る。それを用意できないなら、同じ低レベル領域でも所有権の検査を処理系に任せられる言語や C++ を先に検討する。
- 移植性がどこまで必要か。 規格を明示し処理系依存を避けて書けば、C は動かせる対象機の幅広さで今も抜きん出ている。逆に単一環境で完結する用途なら、あえて C を選ぶ動機は薄い。
学ぶ対象としての価値は、この判断とは別に残る。ポインタと手動のメモリ管理を一度自分で書いておくと、他の言語が裏で何を代行しているかが見えるようになる。
この記事は役に立ちましたか?
関連用語
関連する記事
有名プログラマの読書習慣 - 天才たちは何を読んできたのか
リーナス・トーバルズ、まつもとゆきひろ、ビル・ゲイツなど、著名なプログラマたちの読書習慣と愛読書を紹介します。天才たちの読書スタイルから学べることとは。
Linux 本ガイド - コマンドライン / しくみ / 性能の 3 層で選ぶ技術書
Linux を学ぶ技術書の選び方を 3 層 (コマンドラインの操作 → カーネルのしくみ → 性能と運用) で整理。新しい Linux の教科書や [試して理解] Linux のしくみなどの定番書の使い分けと、学ぶ順番を解説します。
JavaScript / TypeScript 本ガイド - 入門から型で守る実務コードまで
JavaScript と TypeScript を 1 本の学習ルートとして捉えた技術書の選び方。JavaScript の入門書、言語の背骨を通す体系書、TypeScript の型システムを設計の武器にする本、React/Next.js の実践書まで 2026 年 8 月時点の定番で案内します。