2016-12-20 3 views
1

プログラマーとして私は小さな機能のマクロ定義にキーワードインラインを好んで教えてきました。私は、inlineはタイプチェックをしないマクロ定義のためにより安全であることがわかっていますが、インラインはコンパイラが実際にコードを置き換える要求であり、コンパイラはその要求を受け入れる必要はないと言われています。私はマクロリクエストがあるのだろうと思っていますか、それとも頭がおかしくないことが保証されていますか?マクロはオーバーヘッドを保証していませんか?

+0

も一種のオーバーヘッドです。 –

+2

コンパイラは、C++仕様に従って、すべてのマクロが最初に展開された場合と同じコードを生成する必要があります。 –

+3

マクロは、プリプロセッサによってコンパイル中にインライン展開されることが保証されています。ただし、これは「オーバーヘッドなし」を意味するものではありません。 *大きい*コードは*遅い*コードかもしれません。そのため、コンパイラはインライン化の要求を無視することにしました。あなたはこれについて心配する必要はありません。コンパイラがそれを処理させます。 –

答えて

8

マクロは、コンパイルの前に実行されるテキスト置換であり、関数呼び出しの方法で「実行時オーバーヘッド」を持つことはできません。コンパイラは最適化を有効にしてinlineキーワードを使用しなくても関数を自動的にインライン化するため、関数の代わりにマクロを使用するのは良い理由ではありません。さらに、リンク時間最適化-fltoを使用すると、TU間のインライン化が可能になります。

2

マクロはコンパイル時のものです。コンパイルされたコードにマクロとして表示されることはありません。あなたは

#define MyVar 5 

のようなものを定義し、コード内で行う場合:

double y = MyVar*MyVar; 

これはまさに同様です:コンパイル時に

double y = 5*5; 

MyVarマクロはがでに置き換えられますあなたが定義した値。実行時にはオーバーヘッドが全くありません。

+1

s/compile-time/preprocessorです。 – Barry

+2

@Barry:プリプロセッサはコンパイラの一部です。 –

+0

@KeithThompson同じバイナリの一部ですが、前処理ステップは実際のコンパイルステップの前に行われます。 – Barry

1

マクロはプリプロセッサ機能です。

プリプロセッサは純粋にテキスト形式でプログラムを修飾します。プリプロセッサを個別に実行すると、実際にその結果が表示されます。

gccでは、gcc -Eまたはcppのいずれかを使用できます。 私はマクロをデバッグするときにこれを頻繁に行います。

例のmain.c:gcc -E main.c | tail

#include <stdio.h> 

#define MC_repeat(X) \ 
    for(int _i=0;_i<(X);_i++) 

#define rt return 

#define MC_xputs(X) if(0>puts(X)) rt -1; 


int main() 
{ 
    MC_repeat(5) 
     MC_xputs("hello world"); 
    rt 0; 
} 

が出力:

# 2 "main.c" 2 
# 11 "main.c" 

# 11 "main.c" 
int main() 
{ 
    for(int _i=0;_i<(5);_i++) 
     if(0>puts("hello world")) return -1;; 
    return 0; 
} 

あなたは、このようなソースをコンパイルすると、あなたが最初にpreprocesserを実行し、その後に結果をパイプかのように、それが効果的ですコンパイラは適切です。

gccの実際(あなたがより良いエラーメッセージを取得する)このようにそれを行うませんが、あなたがそれを強制することができます:長いコードを作る

#actually pipes preprocessor output to the compiler proper 
gcc -E main.c | gcc -x cpp-output 
+0

* "純粋にテキスト" *は不正確です。プリプロセッサはいくつかの解析を実行します。 'MC_repeat(5)'と '(MC_repeat)(5)'を交換すると、プリプロセッサはもはや 'MC_repeat'シンボルを置き換えません。 – IInspectable

関連する問題