C ++プリプロセッサで

1.概要

予約注文は、#文字で開始する我々のプログラムの先頭でオーダーです。なぜそれがプリオーダーと呼ばれていますか?これらのコマンドは実装上ではなく、アセンブリコードにコンパイル時に最初のステップであるためです。

ステップコンパイラコード:

  1. 前処理。処理#は#がそう、最初のステップは、もはやCEを書きませんかに関係なく、コマンドを定義して、コメントを削除し、含まれています。

  2. コンパイル。本当に(O2はのいくつかを変更します開いた)コードの構文解析をコンパイルしてアセンブリファイルを生成します。

  3. コンパイル。マシンコードにアセンブリコード。
  4. リンク。移転、コンピュータリンクライブラリに応じて、実行可能ファイル

使用すると-E-S-c、1-2手順、1-3ステップだけステップ1を実行することもできます。この記事についての知識に疑問がある場合は、使用することもできますg++ -E 1.cpp -o 1.i事前処理取得する.i文書に経験を。さらに-Sまた、アセンブリコードを取得するために使用されます。

少し使用中のOIにおけるプリコマンドのほとんどは、しかし、強力なプリプロセッサがあります。

#記号は、行の最初の非空白文字でなければなりません。しかし、あなたはまた、再生することができ\、単にコメントとして、次の行にコンテンツを。

#define pi 3.14159 \
26535
//This is an \
example

これは、次の行のコンテンツの移動を置きます。

羅区エディタはそう表示されませんでしたが、あなたは、次の行を見つけることができますローカルエディタはコメントまたは前処理スタイルとなっています。

次のように共通の事前受注は以下のとおりです。

#include 包含头文件
#ifdef 或 #if defined 如果定义了一个宏, 就执行操作
#ifndef 或 #if !defined 如果没有定义一个宏,就指执行操作
#define 定义一个宏
#undef 删除一个宏
#pragma 自定义编译器选项,指示编译器完成一些事

ここでは最も一般的に使用される前処理の3つがあります:#include#define#pragma

2.の#include

これは、最も一般的なファイルコマンドが含まれています。

どんなにあなたがどのように強力で、手書きすることができますどのようなものでなく、必要はありません#include <cstdio>

コマンドは、基本的に指定したファイルの関数である変数、マクロ、およびすべてのインポートされたファイルの内容全体をコピーして、中にあなたのコードに貼り付けると、理解することができます。

それは単純に貼り付けされている場合しかし、#を繰り返し二回定義されているはずCEの息子が含まれます。しかし、標準ライブラリの使用マクロはこれを避けるために(後述)。我々はまた、ヘッダファイルを記述する必要があることに注意してください。

質問0:の#include角括弧は、それに接続する必要がありますか?

実際には、#includeコマンドは引用符は完全に許容され、角括弧を使用する必要はありません。

違いは、引用符は、コールが標準のライブラリファイルを見つけることができません、コンパイルするファイルを見るために優先権を与えることです。

もちろん、OIer条件のため、#include <cstdio>#include "cstdio"何の違いもないでしょうが、今回は角括弧より標準化しました。

C ++を使用して、独自のゲームを開発する場合、管理を容易にするために、あなたはライブラリを標準として保存された別のファイルに類似し、同じ機能を使用することができます。必要なときにあなたが引用符を使用する必要があり、含まれています。

質問1:標準ライブラリを参照するとき、なぜ.Hヘッダーファイルを追加しませんか?

実際には、C言語を追加するだけ書くことができます#include <stdio.h>#include <math.h>

Cの例により除去し、前にこれらの文書の拡張でC ++#include <cmath>

しかし、あなたは古い言い回しを使う場合は、これらの伝統的なライブラリは、まだコンパイルされますが、標準化されていなかったことができます。

しかし、新しい(たとえば、C ++など、コンテンツのためiostreamstack)を追加することはできません.hアップ。

誰かが言って、試してみました#include <string.h>缶を!しかし、string.hそれはのC言語に対応しcstringている++ではなくCの新しいライブラリstringかつての使用が定義されていないstringタイプ。cstringライブラリは、機能及びそのようなstrlenをmemsetを、memcpyのような機能メモリ操作のいくつかの文字列を提供することです。

質問2:ユニバーサルヘッダファイルは本当に強力な?

今NOI)(Pはすでにユニバーサルヘッダファイルをサポートしています#include <bits/stdc++.h>

(スラッシュはバックスラッシュ間違っ可能CEはないことに注意してください)

実際にはどのような彼は、完全にあなたの心を含めることは不可能ですが、あなたは絶対に内部詰め込むすることができます。

C++11また、新に含まれてrandomunordered_mapこのようなライブラリーとして。
STDC ++。H元のファイルを参照してください。

それは普遍的ではできませんが、OIは確​​かに完全に十分でした。

噂!ユニバーサルヘッダファイルと走行速度を遅く、メモリがほとんど無視できる増加しません。使用されなかったコンパイルされた主なものは、離れて最適化されます。

そして、あなたは常にダースのヘッダファイルをもたらすことができる、全く説得力がない、1万悪いもう一度言います

もちろん、ソースコードのサイズを大きくし、時間をコンパイルすることが可能で、その後、卵

質問3:なぜ私は他の人がファイルをインクルードプログラムの途中で魔法のような操作を持って見ていますか?

彼は前に言った#includeことは、このコマンドの機能に書かれているかのように、指定されたファイルの性質は、この行にコピーされ、それはこの効果のみの関数です。

void func()
{
    #include "test.h"
    mmm();//可以使用test.h里的函数
}

int main()
{
    func();
    mmm()//CE。不能使用test.h里的函数。
}

標準ライブラリはまた、名前空間の問題を伴うので、しかしOIで、そうすることはできません。

Quetion 4:最後に、独自のヘッダファイルを書くには、使用する方法ですか?

標準によれば、その後、.hマクロおよび機能は大きな塊、変数宣言を格納するために(つまり、関数名と関数の最初の行のパラメータリスト)と同じ名前.cppのストレージ機能の具体的な実現。.h私が書きました#include "test.cpp"メインプログラムはTEST.Hがいる限り、ライブラリの関数として使用することができます含まれています。

しかし、労力を節約するために、我々はできる.h、直接良い関数の定義では、あなたは、メインプログラムで直接選択することができます#include "test.cpp"コピー&ペーストコマンドのエッセンスが含まれています、また、何の問題を記述していません。

ユニバーサルヘッダファイルを使用していない変数名を使用してくださいy1, next, time, rand

多くの一般的な単語を含むが最善ではない、いくつかのWindowsはできますが、CEを評価する時期。

3.の#define

#DEFINEマクロ定義コマンドは、置換文字列のためのコード、と呼ばれています。最も有用な前処理指令であります

パラメータなし1.マクロ

#define MAX 10000
if (9874 > MAX)
    return 0;

コードは、マクロMAXに定義され、「MAX」の後には10000を表します。式が偽の場合。

constこのメソッドは、定数を定義する代わりに使用することができる、とだけコードの交換、ランタイムはスペースを占有しません。また、長い標準ライブラリ関数名を簡素化するために使用することができます。

また、複数の操作を(例えば弾性率)を実行するには、この定数が必要な場合は、これについてはあまり気にしない、またはそれ以上に自分自身を参照して、CONSTは、個人が完全にテストされていないを通じて、より高速で確かにケースですが、その差の効率が小さい書かれると言われていますどのように書くの一種。

注意:

マクロ文字列や注釈を置き換えるものではありません1.の#define(ナンセンス)

2.必要性が完全にマクロ「スーパー」と定義され、「スーパー」セクションが置換されていないように、あるいはマクロ一致します。

引数付き2.マクロ

実際には、マクロ機能で、あなたはパラメータを持つことができます。

例:円の半径と周辺部と面積を求めます。

#define pi 3.14159
#define AREA(i) i*i*pi

double d;

int main()
{
    cin >> d;
    cout << AREA(d)<< endl ;
    return 0;
}

我々はAREA(i)は、表示された後、フォームのこのAREA機能のようなマクロを書くときに
最初の括弧2で見つかった、つまり、I = 2は、その後、交換を行います。

また、文字列だけので、それだけではなく、あなたも発現、機能、あるいはコードセグメントを定義することができます。#define定数を定義することができます。

#define sum(a,b,c) (a)+(b)+(c)
#define max(a,b) (a>b)?(a):(b)
#define fors(a,b) for(int i=(a);i<=(b);i++)

マクロ定義を使用すると、他の機能ながら、の#define最大を理解するために、コードがはるかに容易になります。機能よりも高速ではなく、はるかに高速。

注意:

#defineコマンドマクロコマンドは、最初の単語、マクロ本体の残りの部分です。

#define int long long
#define abc def ghi \
jkl
#define register

最初の文では、最初の選択肢、すなわちINT代表長い長い後、INTです。

第二の文では、唯一のマクロ本体ABCとして交換する、ABCは効果をラップDEF GHI JKL、唯一のバックスラッシュの後にあります。

3番目の文では、すべてのプログラムがregister削除されます、それはデバッグに使用することができます。

専用ケース(完全に文字列、感謝@Black_white_Tony dalaoを交換しません):

我々は、すべてのことを知っているvector <pair<int,int>>>>ための権利として認識され、CEは、スペースを埋める必要があります。しかし、あなたが書いた場合:

#define pii pair<int,int>
vector <pii> a;

最初の文字はnew演算子を構成することができた後の文字と最後を定義した場合、自動的にスペースが追加されますので、しかし、それは正しく、コンパイルすることができます。あなたは使用することができg++ -E、より徹底したのいくつかを見るための指示を。

二つの新しい演算子演算子の設定スペース:<< >> -> ++ && += >=

これはおそらく、今、設計上の問題のSTLのSTLセットの例外です。

注意:C++11そこに直接書き込むことができvector <pair<int,int>>ていますが、マクロ定義ファイルを使用している場合は、まだ前処理を加えたスペースの最初の段階でここになります。

3.高度なアプリケーションのマクロ

##:接続文字列の左右端

#:パラメータの後ろに文字列となる(すなわち、プラス力「」)

#define a(x) p##x
#define b(x) #x

int p1 = 3, p2 = 4;
  
int main()
{
    printf("%d %d\n",a(1),a(2));
    puts(b(qwqwq));
}
//Output:
//3 4
//qwqwq

より一般的な略語が使用されるfor原因とBの変化がもたらす問題を避けるために、。

#define F(i, a, b) for(int i=(a),end##i=(b); i<=end##i; i++)

#ifdef あなたは、マクロを定義する場合

#ifndef あなたは、マクロを定義しない場合

#endif(かっこに相当)は、上記2つの文の終了

標準ライブラリでは、ヘッダファイルを含むそれぞれは、ヘッダを定義するこのファイルは、ファイルが二度目に含まれている場合、ファイルがマクロに含まれていることを示して#ifndef実行されていない偽で、そのように、ファイルをスキップしますあなたは、鉛CEを含める繰り返しを避けることができます。

いくつかのマクロが定義上の異なる環境でコンパイルされている、あなたは面白いことを行うためにこれらを使用することができます。

#ifndef ONLINE_JUDGE
    freopen("testdata.in","r",stdin);
    freopen("testdata.out","w",stdout);
#endif
//很多OJ(包括洛谷)都有这个宏

また、あなたがマクロのデバッグを定義することができる、の初めに使用デバッグ出力文#ifndefだけデバッグ出力アノテーション行を削除する必要がありますので、同封。

その他の定義済みマクロ:( cppreferenceから撮影)

__cplusplus //C++版本号
__FILE__ //文件名
__DATE__ //编译日期
__TIME__ //编译时间
__LINE__ //这一行的行号

4.マクロの失効

定義可能なマクロは、キャンセルすることができるの#undefマクロ名は、(事前定義を含む)マクロを取り消すに直接接続することができます使用されます。

#define sum(a,b) a+b
#define e 2.718
int a=sum(9,6);
double b=e*3;
#undef sum(a,b)
#undef e
#undef __cplusplus

マクロの欠点

Acerは使用すると便利ですが、多くの欠点があります。

I.優先度変更操作
#define DEF 2+3
int a = DEF+5;
int b = DEF*7;

5に変換されないに直接の形でDEF 2 + 3

Aの定義において、 "5 + 2 + 3"、10の値として解釈されるべきです。

しかし、B「2 * 7 + 3」、23の乗算第1のカウント値として解釈されるべきで、我々はない35が欲しいです。

解決策は、パラメータの前後に括弧を挿入することです

II。ノー固定データタイプ
#define MAX 1e6
int a[MAX];

この時点では、CEでしょう。1E6はdouble型であるため、テキスト変換の種類が発生することはありませんここでMAXに置き換えられているので、配列のサイズは、int型することができます。

これは、プラス(INT)の前に、またはconstとして使用して定数を定義しました。

4.の#pragma

私たちは、最速の男を質問時間の最適解を見つける(表をヒットしない場合)の#pragmaは、多くの場合、多くの場合、カードのラインの数十を持っています。したがって、このコマンドを使用することは何ですか?原則カードしばしば、それがあるとは何ですか?

#pragmaコマンドは、コンパイラオプションを指定したり、コンパイラは、いくつかのコマンドをやらせることができます。非常に強力な、ごく表面的な導入があります。

Baiduの百科事典から一部抜粋。

1.の#pragmaかつて

あなたが最もたら、ファイルをコンパイルするコンパイラに伝えることができ、ヘッダファイルの先頭に追加し、重複を防ぐためにも使用することができ、ヘッダファイルが含まれています。以前よりも#ifndef使いやすいが、標準ライブラリは無用です。

2.の#pragmaメッセージ()

括弧内コンパイラの出力文字列を、聞かせて#ifdef可能な出力コンパイル時に特定の情報を。

3.の#pragmaコメント()

自身リンクされたファイルのために、OIは、手動でスタックに拡張するために使用(必ずしも有用ではない)することができます

#pragma comment(linker,"/STACK:1024000000,1024000000")

前記の#pragma GCCターゲット()

ザ・ネットワーク全体に何の正確な定義を捜索していない、おそらく命令として認識されているものをカッコです。速度指令関数よりも速く、それによって加速されます。

#pragma GCC target("popcnt")組み込み関数は、(__builtin_popcountを可能に)倍以上の速度です。

あなたは命令セットを使用する場合以外にも、この命令を含む命令セットで使用することができます。

#pragma GCC target("avx,avx2,sse,sse2,sse3,sse4.1,sse4.2")

5.の#pragma pack()&ポップ()

整列させるための構造

//#pragma pack(4)
struct Node
{
    int a;
    long long b;
}x;

本来このような長い長いと整列INT上の例のように最大の構造体と整列している各変数は、また、8バイトです。そうsizeof x = 16

フレーズがそこに#pragma場合は、各変数が整列して4され、バイトの数は、4よりも本質的に以上に長い長い、4 int型無視されましたsizeof x = 12これはある程度のスペースを節約します。

しかし、実際はそう大きな良いX、より効率的に整列されます。

パック()命令をキャンセルするポップ()を使用することができます

前記の#pragma GCCの最適化()

ブラケットは、コンパイラのパラメータをカスタマイズすることと等価である文字列パラメータにコンパイル。

あなたが番号を入力すると、それはO1 / O2 / O3の最適化となります。コンパイラの最適化が来るをオンにするには、このコマンドを使用します。

しかし、このようなとしてのみ、コンパイラの最適化パラメータ、-oファイル名を指定するには、確かに内部に追加することはできません。

最後に広く流通ネットワークを最適化するために、40行が付属しています:

#pragma GCC target("sse,sse2,sse3,sse4.1,sse4.2,popcnt,abm,mmx,avx")
#pragma comment(linker,"/STACK:102400000,102400000")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")

注意:

  1. このような最適な結果の形而上学は、使用されていない時期に、時には非常に激しい変動し、また、ビルド環境と関連しています。しかし、最悪の場合には使用がコードは、環境CEをコンパイルされません、ありません。
  2. O2 / O3 / Ofast最適化が書き換えサイクルに達しているので、そのようなハルマゲドン度と冗長コードを削除し、エラー形而上学のコード結果の意図を変更することは容易です。これらは、最適化を使用する場合は、そのコードの仕様を確認する必要がありそうでない場合は、形而上学的な問題があるでしょう。
  3. (Pがない最高の(そして、あなたがダウンしてバックアップすることはできません、使用することはできません))NOIを知ってはいけません

5.その他

導入の数行を過ごすためにここにいくつかのコマンドがあります。

#error //在这一行显示一个CE信息,并中断编译
#warning //在这一行显示警告信息
#line //指定下一行的行号
#if //如果满足则执行,后面应接布尔表达式,以#endif结尾
#elif //#if语句的分支

Sahuaの終わり、同行する感謝

おすすめ

転載: www.cnblogs.com/ofnoname/p/11621345.html