プリプロセスを追う (関数の宣言)

.i ファイルの中ではどこで関数の宣言が行われているのでしょうか? ConsoleApplication1.cpp の中にある、
#include <stdio.h>
#include "MySource.h"

int myFunc();

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
}

int myFunc()
{
    return 123;
}
に当たる部分を .i ファイルから探してみます。

手順

.i ファイルを開きます [ソリューション エクスプローラー] よりプロジェクト項目を右クリック、[エクスプローラーでフォルダーを開く] を押下します "Debug" フォルダを開きます "ConsoleApplication.i" をテキストエディタで開きます 今回探したいのは #include "MySource.h" 部分でした。 ですから、テキストエディタの検索機能で "MySource.h" などと検索します 私の環境では ConsoleApplication.i の 10698 行目に該当語句がありました また、.i ファイルの終端が 10720 行目であったことも確認できました .i ファイルから重要箇所をこちらに抜粋します
#line 1 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\MySource.h"
#pragma once
int mySourceFunc();
int mySourceFunc1(int);
int mySourceFunc2(int, int);
#line 3 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\ConsoleApplication1.cpp"

int myFunc();

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
}

int myFunc()
{
    return 123;
}
今見えているテキストがソースファイル (.c) をプリプロセス処理したものです。また、#include 処理の実態です。基本的には指定したテキストファイルの中身を展開しているに過ぎません。("#line" 行はコメントです) こちらの前半部分で、mySourceFunc 関数の宣言を
#include <stdio.h>

int myFunc();
int mySourceFunc();
int mySourceFunc1(int);
int mySourceFunc2(int, int);

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
}

int myFunc()
{
    return 123;
}
というように、include を使用せずに行っておりました。プリプロセス処理後である .i ファイルと比べてみると、同じような形になっていることがよくわかると思います。 プリプロセスでは数多くのヘッダーファイル (.h) がソースファイル (.c/.cpp) に取り込まれ、一見ややこしいのですが、プリプロセス後には一つのテキストファイル (.i) になるのだ、ということが見て取れると思います。

printf の宣言箇所

.i ファイルですが、ファイルの大部分 (空行込みで10000行近く) が、たった一行、#include <stdio.h> に起因することに気づかれましたか。標準 C ライブラリのヘッダファイルです。これらすべての説明は私にはしきれませんし、できません。 しかし、使用している関数の宣言くらいは確認してみます。 いまのサンプルソースでは printf 関数を使用しています。printf 関数は stdio.h で宣言されている関数です。では "ConsoleApplication.i" に宣言箇所があるはずです。 "ConsoleApplication.i" をテキストエディタで開きます。 "printf" で検索します。 私の環境では 9237 行目の下記の箇所が該当しました :
    #line 948 "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.22000.0\\ucrt\\stdio.h"

    
    __inline int __cdecl printf(
            char const* const _Format,
        ...)
ヘッダーファイルも確認します。 Visual Studio で ConsoleApplication1.cpp を開きます printf の呼び出し箇所で F12 を押下します 次の箇所が表示されました これを見るに Windows の開発環境における printf はインライン関数として記載されており、ヘッダファイルに実装があったのですね。実際の処理は _vfprintf_l で (さらに辿ると __stdio_common_vfprintf で) 行うようです。(私はこれを書いている今初めて知りました) このページはここで終わります。このページでは下記を行いました。
ところで、.i ファイルとヘッダでは表示されている文字列が少し異なります
.i ファイル__inline int __cdecl printf
ヘッダファイル_Check_return_opt_ _CRT_STDIO_INLINE int __CRTDECL printf
それは、ヘッダファイル側はマクロで書かれているためです。マクロについては次のページで説明します。