C言語①(2025/04/23)

【授業の進め方】
Cの絵本をベースに補足していく形式で進行。
・・・前期で終わる予定。

→後期はC++の知識を身に着けていく
マップエディタなど、簡単な題材で「クラス」を実装する方向性

【コンソールプログラム】
「コマンドプロンプト」上で動くプログラム。

Winキー+cmd または コマンドプロンプト を検索

c:\USER>
・・・現在の「ディレクトリ(フォルダ)」を指している。

dirの説明(ディレクトリ内のファイルとフォルダを表示する)
exeの説明(Windows系のOSではexeが実行ファイル)
授業ではVisualStudioを実行環境として使っていく。

【今日のコード】
#include<stdio.h>

int main(void)
{
printf(“Hello World!\n”);
return 0;
}

#includeとは、ソースファイル内に「ヘッダーファイル」を取り込む「疑似命令」。
stdio.hなどの(システムヘッダーファイル)は<>で囲う。

そのほか(自作のヘッダーファイルなど)は””で囲う。

void 引数なし

int 戻り値

インデントを適切に入れる(Tab)

「コードレベル」の区別に役立つ。大規模になればなるほど重要。

コードレベル
コードレベルは、コードのネスト(入れ子)構造の深さや、そのレベルごとの役割を指します。例えば:

  • トップレベル: メインの流れやエントリーポイント(例: main() 関数)。
  • 中間レベル: メインの流れの中で呼び出される関数やロジック。
  • 低レベル: 細かい処理や内部的なアルゴリズムの部分。

ネストの深さを管理することで、コードの複雑さを抑えることができます。一般的に、深すぎるネスト(コードが何重にもインデントされている場合)は、読みづらさやバグの原因になるため、避けるべきです。

インデント
インデントとは、コード内で行頭をスペースやタブでずらすことを指し、構造を視覚的に分かりやすくするために使われます。例えば、ブロック内のコードを階層的に表現する際に使用します。

インデントのルールやベストプラクティス:

  1. 統一性: インデントは、タブまたはスペースのどちらかに統一する(スペース4つが一般的)。
  2. ネストの明確化: 条件分岐やループごとにインデントを追加して、ネストを明示する。
    if (condition) { // ここにインデントが必要 doSomething(); }
  3. 深すぎないネスト: ネストは3〜4レベル以内に収めると、可読性が向上します。

エントリーポイントについて

main関数:プログラムのエントリーポイント(つまり、初めに実行されるもの)。

WinMain関数:ウインドウプログラムのエントリーポイント

Return 0;
→コンソールプログラムでは不要。ウインドウプログラムでは必須。
これはプログラムのエントリーポイントと実行環境の違いによるものです。それぞれのケースについて説明します。

●コンソールプログラムの場合
コンソールプログラムでは、main()関数がエントリーポイント(プログラムの開始地点)です。C++の標準では、main()関数が明示的にreturn 0;を記述しなくても、コンパイラが暗黙的にreturn 0;を追加します。これは、プログラムが正常に終了したことを示します。
Cの標準規格(ISO C Standard)では、main()関数の最後に明示的なreturn 0;が記載されていない場合でも、コンパイラが自動的にreturn 0;を追加することになっています。これは、コンソールプログラムが正常終了したことを示すための便利な仕様です。

この仕様は、C++プログラムの可読性を向上させる目的で追加されたものです。ただし、明示的にreturn 0;を記載することは推奨されます。理由は:

  • コードの明確化: 他の人がコードを読んだときに、プログラムがどのように終了するか一目でわかる。
  • 一貫性の維持: 大規模プロジェクトでのコーディングスタイルに合わせやすい。

一方、ウィンドウプログラム(WinMain)では、OSが終了コードを必要とするため、自動的な補完は行われないという違いがあります。

●ウィンドウプログラムの場合
ウィンドウプログラム(Windowsアプリケーション)の場合、エントリーポイントは通常WinMain()という関数です。この関数の戻り値は、Windowsオペレーティングシステムが必要とする情報を提供します。

ここで、returnの値はOSに対して、プログラムが成功したかどうか(終了コード)を伝える役割を持ちます。コンソールプログラムとは異なり、WinMain()では明示的に戻り値を指定する必要があります。これは、OSがプログラムの終了状態に基づいて次の動作を決定するからです。

違いの理由

簡単に言うと、ウィンドウプログラムではOSが終了コードを明確に受け取る必要があるため、明示的なreturnが必要です。一方、コンソールプログラムではmain()関数に対して暗黙的にreturn 0;が適用されるため、記述を省略しても問題になりません。

WinMain()でもreturn 0;を自動的に追加してくれればいいのでは?
「WinMainでも自動的にreturn 0;が補完されていいのでは?」という考えは非常に合理的に感じられるかもしれません。ただ、これにはWindows OSの設計上の理由が絡んでいます。深堀りして説明しますね。

理由1: OSとの通信

Windowsプログラムでは、WinMain()関数は単にプログラムを終了するだけでなく、OSに終了コードを通知する役割を持ちます。終了コード(典型的には0は正常終了を示し、非ゼロ値はエラーを示します)は、Windows OSがプログラムの終了状態を管理したり、他のプロセスがその情報を利用したりする際に必要です。

例えば:

  • Windowsのコマンドラインやバッチ処理で、あるプログラムの終了コードを次の処理に渡す場合があります。
  • この終了コードがエラーコードとして使われると、他のシステムコンポーネントに明確なエラー原因を伝えることができます。

main()はこうした用途が限定的である一方、WinMain()はOSレベルのプロセス管理において、より重要な役割を担うのです。

理由2: カスタマイズ性の確保

WinMain()では、プログラム開発者がエラー状態を詳細に伝えるために、任意の数値を終了コードとして返すことが求められる場合があります。たとえば、以下のような状況が考えられます:

  • return 1; はファイルが見つからないエラーを示す。
  • return 2; はネットワーク接続エラーを示す。
  • return 0; は正常終了を示す。

このように、終了コードを具体的に指定することで、プログラムの意図をOSや他のプロセスに明確に伝えることができます。自動的な補完が行われると、この柔軟性が失われる可能性があります。

理由3: C++規格とOS仕様の違い

Cのmain()関数は、C規格で暗黙的なreturn 0;が許容されるよう設計されています。一方、WindowsのWinMain()はC++規格に完全に従うものではなく、Windows専用の仕様に従います。この仕様では明示的なreturnを要求することで、OSとの確実な通信を保証しています。

なぜ「自動補完」が適用されないのか?

Windowsの設計者は、プログラム開発者に終了コードの管理を完全に委ねることで、より細かい制御やエラー状態の管理を可能にしています。これは、GUIプログラム(ウィンドウプログラム)が多様な終了状態を必要とすることが理由です。

簡単にまとめると: WinMain()では終了コードがOSとの通信の一環として重要な役割を担うため、明示的な指定が必要ということです。

コメント

タイトルとURLをコピーしました