プログラマーとして私は小さな機能のマクロ定義にキーワードインラインを好んで教えてきました。私は、inlineはタイプチェックをしないマクロ定義のためにより安全であることがわかっていますが、インラインはコンパイラが実際にコードを置き換える要求であり、コンパイラはその要求を受け入れる必要はないと言われています。私はマクロリクエストがあるのだろうと思っていますか、それとも頭がおかしくないことが保証されていますか?マクロはオーバーヘッドを保証していませんか?
答えて
マクロは、コンパイルの前に実行されるテキスト置換であり、関数呼び出しの方法で「実行時オーバーヘッド」を持つことはできません。コンパイラは最適化を有効にしてinline
キーワードを使用しなくても関数を自動的にインライン化するため、関数の代わりにマクロを使用するのは良い理由ではありません。さらに、リンク時間最適化-flto
を使用すると、TU間のインライン化が可能になります。
マクロはコンパイル時のものです。コンパイルされたコードにマクロとして表示されることはありません。あなたは
#define MyVar 5
のようなものを定義し、コード内で行う場合:
double y = MyVar*MyVar;
これはまさに同様です:コンパイル時に
double y = 5*5;
、MyVar
マクロはがでに置き換えられますあなたが定義した値。実行時にはオーバーヘッドが全くありません。
マクロはプリプロセッサ機能です。
プリプロセッサは純粋にテキスト形式でプログラムを修飾します。プリプロセッサを個別に実行すると、実際にその結果が表示されます。
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
* "純粋にテキスト" *は不正確です。プリプロセッサはいくつかの解析を実行します。 'MC_repeat(5)'と '(MC_repeat)(5)'を交換すると、プリプロセッサはもはや 'MC_repeat'シンボルを置き換えません。 – IInspectable
- 1. Appleはプッシュの配送を保証していませんか?
- 2. Scipyのsign()は動作保証されていませんか?
- 3. Excelマクロ:なぜこれは正しいディレクトリに保存されませんか?
- 4. Excelのマクロは何もしていませんか?
- 5. コード契約では、ループの検証が保証されていません
- 6. C#の自動プロパティでオーバーヘッドが発生していませんか?
- 7. jQueryはRadioButtonListを正しく検証していませんか?
- 8. Firebaseは認証リストのFacebookユーザーを保存していません
- 9. プリプロセッサは許可していません「:」トークンでのマクロでプロパティ
- 10. ドメインは検証しますが保存しません
- 11. symfony 3はデータベースからユーザを認証していません
- 12. なぜClojureはマクロ内のプライベート関数をサポートしていませんか?
- 13. 保証されていません3.0.3 IntelliJ IDEAの依存関係が機能していません
- 14. CSS検証はもはや関連していませんか?
- 15. iPhone - UIWebviewは認証をサイトに保存しません
- 16. カーネルはコンパイルされたファイルに対して後方互換性を保証していませんか?
- 17. Hibernateはデータを保存していませんか?
- 18. Laravelはリクエストからのファイルを保存していません
- 19. IE8はクッキー値を保存していませんか?
- 20. Androidはテキストを保存していませんか?
- 21. std :: vectorはデータを保持していませんか?
- 22. FacebookRedirect.axdはクエリ文字列を保存していませんか?
- 23. なぜaddSubviewはビューを保持していませんか?
- 24. Firebaseはデータを保存していませんか?
- 25. VBAマクロがbatファイルを実行していません
- 26. Jsonはファイルの内容で検証していませんか?
- 27. PHPのWebサイト検証は機能していませんか?
- 28. マングースは正しいスキーマを保存していません
- 29. Thinky.io hasManyは新しいモデルインスタンスを保存していません
- 30. Silverstripe:ConfirmedPasswordFieldは新しいパスワードを保存していません
も一種のオーバーヘッドです。 –
コンパイラは、C++仕様に従って、すべてのマクロが最初に展開された場合と同じコードを生成する必要があります。 –
マクロは、プリプロセッサによってコンパイル中にインライン展開されることが保証されています。ただし、これは「オーバーヘッドなし」を意味するものではありません。 *大きい*コードは*遅い*コードかもしれません。そのため、コンパイラはインライン化の要求を無視することにしました。あなたはこれについて心配する必要はありません。コンパイラがそれを処理させます。 –