スコルの知恵袋

主にプログラミング関係の気になったこと等をまとめたブログ

【g++】 どこからインクルードされているかを調べる

結論

-H オプションを使おう。

はじめに

競プロで #include <bits/stdc++.h> をするとコンパイル時間が若干長くなる。 この対策としてコンパイル時間短縮のためにプリコンパイル済みヘッダを作ったものの、ちゃんと意図した通りに使われているかが不安だったので調べたかった。

インクルード元の調べ方

g++(1) manページ に記載されている g++(gcc) のオプションを眺めると、

-H 通常の動作に加えて、使用されたヘッダファイルの名前を表示します。

というものがあった。これを使うと、例えば次のようになる。

g++ code/A.cpp -H

コンパイルするコード (code/A.cpp)

#include <bits/stdc++.h>

using namespace std;

int main() {
    int N;
    cin >> N;
    vector<int> A(N);
    for (int i = 0; i < N; i++) {
        cin >> A[i];
    }
    sort(A.begin(), A.end(), greater{});

    multiset<int> st;
    priority_queue<int> pq;
    for (auto a : A) {
        st.emplace(a);
        pq.emplace(a);
    }

    for (auto a : A) {
        int b = *prev(st.end());
        st.erase(prev(st.end()));
        int c = pq.top();
        pq.pop();
        if (!(a == b && a == c)) {
            cout << "No" << endl;
        }
    }
    cout << "Yes" << endl;
}

標準エラー出力:

. /usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h
.. /usr/include/c++/11/cassert
... /usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h
.... /usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h
..... /usr/include/features.h
...... /usr/include/features-time64.h
....... /usr/include/x86_64-linux-gnu/bits/wordsize.h
....... /usr/include/x86_64-linux-gnu/bits/timesize.h
(以下省略)

このように再帰的にどのヘッダファイルが実際に読み込まれているかが表示される。

bits/stdc++.h のプリコンパイル済みヘッダを作って、コンパイル時にその位置を指定したうえで同じことをすると次のようになる。

g++ code/A.cpp -I include/ -H

標準エラー出力:

x include/bits/stdc++.h.gch/c++17_optimize.gch
! include/bits/stdc++.h.gch/c++17_no_option.gch
 code/A.cpp

どうやらプリコンパイル済みヘッダの場合は x やら ! が表示されるみたい。 /usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h が読み込まれていないので、おそらく ! が付いているものが使用されていると思う。

実際に、余計なオプションを付けてコンパイルするとこうなる。

g++ code/A.cpp -Os -I include/ -H

標準エラー出力:

x include/bits/stdc++.h.gch/c++17_optimize.gch
x include/bits/stdc++.h.gch/c++17_no_option.gch
x include/bits/stdc++.h.gch/c++17.gch
. /usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h
.. /usr/include/c++/11/cassert
... /usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h
.... /usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h
..... /usr/include/features.h
...... /usr/include/features-time64.h
....... /usr/include/x86_64-linux-gnu/bits/wordsize.h
(以下省略)

余談: プリコンパイル済みヘッダの効果

code/A.cpp で実験してみるとこうなった。

プリコンパイル済みヘッダなし:

time:
        real: 1.06 s
        user: 0.94 s
        sys:  0.06 s
memory:
        max: 203372 KB

プリコンパイル済みヘッダあり:

time:
        real: 0.38 s
        user: 0.27 s
        sys:  0.05 s
memory:
        max: 139528 KB

割と早くはなる。競プロの成績を左右するほどのものではないけど、若干ストレスは減る。