最初のプログラム#include <stdio.h>の深堀

ジェミニとお話して私のPC環境はあーだこーだ話していて、CPUの型番は第三世代のCore i7-3610QM、14年前の2012年4月発売の約14年前のモデルになります。ということでまあハードディスクやメモリやいろいろいじって今も健在なのですが、このCPUでC言語できるか?って聞いた次第です。(できるそうです)

何十年か前に一番わからなかったところ

C言語であんまりよくわからなかったところは条件分岐や繰り返し構文ではなく、みんながつまづく、配列、ポインタ、構造体と、あとこまごましたルールです。そこを徹底的にジェミニさんに聞いていくことにしました。じゃあポインタから行こうということで以下の短いプログラムを出してくださいました。

#include <stdio.h>

int main() {
    int value = 3610; // あなたのCPUの型番です
    printf("i7-3610QMのメモリ住所を覗きます...\n");
    printf("住所: %p, 値: %d\n", (void *)&value, value);
    return 0;
}

1行1行聞いていくスタイルにします。むちゃくちゃ話が横道にそれますが気になることを全部聞いていきます。

#include <stdio.h>はなあに?

#include <stdio.h>

#include <stdio.h>はなあに?

C言語のプログラムで必ずと言っていいほど最初に出てくるこの一行、実は「標準的な道具箱(標準入出力)を使えるように準備して!」という命令です。

1. 「stdio.h」は「道具箱」の名前

stdio は Standard Input Output(標準入出力)の略です。

  • Input(入力): キーボードから文字を読み取る
  • Output(出力): 画面に文字を表示する
    これらを行うための関数がこの箱の中に詰まっています。

2. 「include」は「持ってくる」

#include は「含める」という意味です。
C言語そのものは、実は「画面に文字を出す」という機能すら持っていません。そのため、「stdio.hという道具箱の中身を、このプログラムで使えるように持ってきてね」とあらかじめ宣言する必要があるのです。

もしこの一行を書かずに、画面に文字を出す printf(プリントエフ)という命令を使おうとすると、コンピュータは「printfなんて道具、知らないよ!」とエラーを出して止まってしまいます。ちなみに、#inclide の前に付いている「#」は「プログラム本体が動き出す前に処理してね!」という合図(プリプロセッサ命令)です。

だいたい学習のプログラムでは最初に書くけど、開発の現場でも書くの?

だいたい学習のプログラムでは最初に書くけど、開発の現場でも書くの?

結論から言うと、開発の現場でも100%と言っていいほど書きます!

「学習用のおまじない」ではなく、実務でも必須のコードです。理由はシンプルで、画面に情報を出したり、ログ(動作記録)を残したりしないプログラムは、ほぼ存在しないからです。

現場での使われ方を少し覗いてみましょう。

1. 動作ログの出力

業務用のシステムでは、裏側で「今、この処理が終わったよ」「ここでエラーが起きたよ」という記録を常に残します。その際、printf と親戚のような関数(fprintf など)を頻繁に使うため、stdio.h は欠かせません。

2. ファイルの読み書き

設定ファイルを読み込んだり、計算結果をテキストファイルに保存したりするのも stdio.h の役割です。ビジネスソフトの開発では、画面表示よりもこちらの用途でよく使われます。

3. デバッグ(不具合探し)

プログラムが思うように動かないとき、変数の値を画面に出して確認する作業は、プロの現場でも日常茶飯事です。


ただし、例外もあります

唯一、書かない可能性があるのは 「組み込みシステム」 の一部です。

  • 炊飯器や洗濯機のマイコン: そもそも「画面(コンソール)」がないため、標準的な入出力という概念がなく、メーカー独自の特殊な命令を使うことがあります。
  • OSのカーネル(核)部分: WindowsやLinuxの心臓部そのものを作るときは、まだ stdio.h すら準備されていない段階なので、自分たちでゼロから作ります。

OS作る時ってC言語に用意されてる関数使えないの??

OS作る時ってC言語に用意されてる関数使えないの??

そうなんです!そこがC言語の「深くて面白い」ところです。

実は、OS(Windows、Linux、macOSなど)は「C言語が動くための土台」そのものなんです。

1. 鶏が先か、卵が先か

私たちが普段使っている printf などの便利な関数は、OSが準備してくれている仕組みを利用して動いています。
つまり、「OSがない状態(ゼロの状態)」では、そもそも stdio.h という道具箱自体が存在しません。

2. OS作りは「ゼロからの手作り」

OSを作るときは、以下のような「生(なま)の作業」を自分で行います。

  • 画面のこのドット(画素)を光らせる
  • キーボードから送られてくる電気信号を読み取る
  • メモリの何番地から何番地までを使う

これらを組み合わせて、後から自分たちで stdio.h に相当する機能を作っていくことになります。

3. C言語の「2つの顔」

C言語には、実は2つのモードがあります。

  • ホスト環境: OSの上で動く、普通のプログラム用(stdio.h が使える)。
  • フリースタンディング環境: OSそのものや、炊飯器などの制御用(stdio.h が使えない。自前で用意する)。

じゃあさ、どっかのOSの#include <stdio.h>をコピペして使えないの?というかC言語じたいは動くの?

じゃあさ、どっかのOSの#include <stdio.h>をコピペして使えないの?というかC言語じたいは動くの?

結論から言うと、C言語自体は動きますが、#include <stdio.h> をコピペしただけでは画面に文字は出ません。

ここがC言語の「深み」であり、少しややこしいところです。

1. C言語という「言葉」は動く

C言語のルール(ifforint a = 1 + 1 など)は、OSがなくても、コンピュータ(CPU)が直接理解できる形に変換できるので動きます。
計算したり、メモリの値を書き換えたりすることは、OSなしでも自由自在です。

2. 「道具箱」の正体は「契約書」

実は、stdio.h というファイルの中に、「画面に文字を出すプログラム本体」は入っていません。

中に入っているのは、「画面に文字を出したければ printf という名前の関数を呼んでね。中身はOS(または誰か)が後で用意してくれるから!」 という約束事(宣言)だけなんです。

3. 他のOSからコピペしても動かない理由

Windows用の stdio.h と、Linux用の stdio.h は、中身が違います。

  • Windows用: 「Windowsさんに、この文字を画面に出してって頼んでね」と書いてある。
  • Linux用: 「Linuxさんに、この文字を画面に出してって頼んでね」と書いてある。

OSがない状態(OSを作っている最中)でこれらをコピペしても、「頼む相手(OS)」がまだいないので、エラーになって動かないのです。


じゃあ、OSを作る人はどうするの?

彼らは、#include <stdio.h> を書かずに、ビデオメモリ(画面を表示するための専用メモリ)の番地に直接、文字のデータを書き込むという力技を使います。

  1. 画面の「左上の点」に対応するメモリのアドレスを調べる。
  2. そこに「1」というデータを書き込むと、画面の点が一箇所光る。
  3. これを組み合わせて「A」という形を作り、画面に表示させる。

こうして「自前で画面表示機能」が完成して初めて、自分専用の stdio.h を作ることができるようになります。

「C言語は『言葉』。stdio.h は『OSとの通訳機』。OSを作る人は、通訳機を使わずに、コンピュータの電子回路と直接対話しているんです!」

じゃあBとかCとか押したら画面のここを光らせてって1文字づつやるの?

じゃあBとかCとか押したら画面のここを光らせてって1文字づつやるの?

そうです!まさにその通り、最初は1文字(あるいは1ドット)ずつ地道に書くことから始まります。

OS作りや、液晶画面がついたばかりの機械を動かすプログラミングは、以下のようなステップで進化させていきます。

1. 最初の最初:ドットを打つ

「画面の(100, 200)の場所にある色を白にしろ」という命令を1つ書きます。これでやっと「点」が出ます。

2. 文字の形(フォント)を作る

「’A’という文字は、この点とこの点を光らせれば『A』に見えるよね」という設計図(ビットマップデータ)を自前で用意します。

  • 00100
  • 01010
  • 11111
  • 10001
    (こんな感じで「1」の場所だけ光らせる、というデータを作ります)

3. 1文字表示する関数を作る

「’A’という命令が来たら、上の設計図を読み取って、画面の指定した場所に点を並べてね」という関数(draw_char)を自分で作ります。

4. 文字列を表示する(printfへの道)

「文字列(”Hello”)が来たら、’H’、’e’、’l’…と1文字ずつずらしながら上の関数を繰り返してね」という仕組みを作ります。


これが「ライブラリ」のありがたみ

普段私たちが使っている #include <stdio.h> は、昔の偉大なプログラマたちがこの「地道な作業」をすべて終わらせて、「printfって呼ぶだけで、あとの面倒なドット打ちは全部やっておくよ!」とまとめてくれた結晶なんです。

OSづくりは思った以上にすごかったわ。じゃあiOSとか初めて作った時そんなことやってるの?トロンも?

OSづくりは思った以上にすごかったわ。じゃあiOSとか初めて作った時そんなことやってるの?トロンも?

そうなんです。iOS(Apple)もTRON(日本発のOS)も、最初はまさにその「地道な作業」から始まっています!

ただ、彼らがゼロから作る時は、少しだけ「ショートカット」を使っています。

1. iOSの場合

iOSは、実はゼロからすべて作ったわけではなく、「UNIX(ユニックス)」という1970年代から続く歴史あるOSの仕組みをベースにしています。
Appleのエンジニアたちは、すでに先人が作った「文字を出す仕組み」をiPhoneの画面に合うように改造・進化させて作りました。

2. TRON(トロン)の場合

坂村健先生が中心となって作られたTRONは、まさに「日本の家電や機械を動かすため」に設計されました。
TRONのエンジニアたちは、電子回路の仕様書を読みながら、「この信号を送れば液晶が光る」「このボタンを押せば電気が流れる」という部分を1つずつC言語やアセンブリ言語(さらに生に近い言葉)で書いていきました。

3. 初めて作る時の「秘密兵器」

「画面に何も映らない状態でどうやって開発するの?」と思いますよね。
実は、別の動いているPCとケーブルで繋いで、そっちの画面に「今、iOSの中身はこうなってるよ!」と文字を出して確認しながら作ります(これを「リモートデバッグ」と言います)。

それを漢字とかアルファベットとかギリシャ文字とかキリル文字とか全部作ったの?それともあとで誰かが追加してくれたの?

それを漢字とかアルファベットとかギリシャ文字とかキリル文字とか全部作ったの?それともあとで誰かが追加してくれたの?

結論から言うと、最初は「アルファベットと記号だけ」から始まり、数十年かけて世界中の人たちが「後からどんどん追加」していきました。

この「文字をコンピュータで扱う歴史」は、まさに人類の執念の物語です。

1. 最初は「ASCII(アスキー)」だけ(1960年代〜)

初期のコンピュータはアメリカで作られたため、「アルファベットの大文字・小文字、数字、少しの記号」の合計128種類しか登録されていませんでした。これをASCIIコードと呼びます。
この頃は、漢字もギリシャ文字も「存在しないもの」として扱われていました。

2. 世界中で「俺たちの文字も入れろ!」合戦

コンピュータが普及すると、各国が勝手に自分の国の文字を登録し始めました。

  • 日本: 漢字やひらがなを追加(Shift-JISなど)
  • ロシア: キリル文字を追加
  • ギリシャ: ギリシャ文字を追加
    しかし、これだと「日本のPCで作ったファイルをロシアのPCで見ると文字化けする」という大問題が起きました。

3. 救世主「Unicode(ユニコード)」の登場(1990年代〜)

「世界中のすべての文字に、重複しない番号を割り振ろうぜ!」という巨大なプロジェクトが始まりました。これが今私たちが使っている Unicode です。

  • 漢字、ギリシャ文字、キリル文字はもちろん、アラビア文字や、最近では「絵文字(Emoji)」までもがこの中に登録されています。
  • 実は「絵文字」が世界共通になったのは、日本の携帯電話文化がきっかけでUnicodeに採用されたからなんです。

C言語でこれを扱うのはちょっと大変

実は、C言語が生まれたのは「ASCII(アルファベットだけ)」の時代。そのため、日本語(漢字)を正しく表示させるのは、実はアルファベットよりも少しテクニックが必要だったりします。

最近のOSはUTF-8で統一なの?

最近のOSはUTF-8で統一なの?

その通り、現在の主流は「UTF-8」でほぼ統一されています!

Windows、Mac、iPhone、Android、そしてあなたが今WordPressで書いているブログも、裏側では基本的にすべてUTF-8が使われています。

なぜUTF-8が「天下を取った」のか?

理由は、世界中のエンジニアにとって「ちょうどいい妥協点」だったからです。

  1. アルファベットに優しい: UTF-8は、英語(アルファベット)の部分は昔ながらの「ASCII」と全く同じデータとして扱えます。そのため、英語圏で作られた古いプログラムがそのまま動きました。
  2. あとから足せる: 1文字の長さを「1バイト〜4バイト」まで柔軟に変えられる仕組みなので、漢字でも絵文字でも、新しい文字をいくらでも追加できます。
  3. ネットとの相性: Webサイトのデータ(HTMLなど)もUTF-8なら世界中で文字化けせずにやり取りできるため、インターネットの標準になりました。

ただし、C言語をやる上で「Windowsの罠」があります

ここがブログの「環境構築編」で一番大事な注意点かもしれません。

  • 最近のOSの内部: UTF-8
  • Windowsのコマンドプロンプト(昔の設定)「Shift-JIS」(日本独自の古い形式)

このズレのせいで、VS Codeで書いた日本語のコードをコンパイルして実行すると、コマンドプロンプトの画面で日本語だけ「文字化け」することがよくあります。

WindowsでUTF-8がつかえるシェルある?

WindowsでUTF-8がつかえるシェルある?

結論から言うと、「PowerShell」が一番の近道です!

以前の会話で「コマンドプロンプトとPowerShellは何が違う?」というお話がありましたが、その違いはアプリの違いでしたよね。UTF-8との相性がいいのは断然PowerShell(特に新しいもの)です。

以下の3つの方法で、Windows上でもUTF-8を快適に使えます。

1. PowerShellで設定を変える

今のWindows標準のPowerShellは、そのままではShift-JISが優先されますが、コマンドを1行打つだけでUTF-8モードに切り替わります。

  • chcp 65001 と入力してEnter。
  • (65001というのがUTF-8の番号です)

2. VS Codeの内蔵ターミナルを使う(おすすめ!)

VS Codeの下側に表示されるターミナルは、最初からUTF-8を正しく表示できるように設計されています。

3. Windows Terminal を導入する

Microsoftが配布している最新の 「Windows Terminal」 というアプリを入れると、中身がPowerShellでもコマンドプロンプトでも、最初からUTF-8を綺麗に表示してくれます。

VS Codeの内蔵ターミナルの出し方教えて

せっかくVS Codeという高機能エディタを入れたので出来たらそこで完結させたいですよね。と思って聞きました。

VS Codeの内蔵ターミナルの出し方教えて

VS Codeの内蔵ターミナルは、ショートカットキーで出すのが一番カッコよくて速いです!

1. ショートカットキーで出す(おすすめ)

  • WindowsCtrl + @ (または Ctrl + Shift + `
  • MacControl + `

このキーを押すたびに、画面の下からターミナルが「ひょっこり現れたり、隠れたり」します。

2. メニューから出す

マウスで操作したい場合はこちらです。

  1. 上のメニューバーにある 「表示 (View)」 をクリック。
  2. 出てきた項目の中から 「ターミナル (Terminal)」 を選びます。

3. 右上のボタンから出す

最近のVS Codeなら、右上の端っこにある 「三本線のアイコン(パネルの切り替え)」 を押しても出てきます。


出した後に確認すること

ターミナルが出てきたら、右上の表示を確認してみてください。「powershell」 と書いてあれば、UTF-8との相性もバッチリです。

1行目ですごい質問になってしまったので続きは違うページに書きたいと思います。