私の連絡先情報
郵便メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
C言語での設定がいくつかあります定義済みのシンボル、直接使用できます。事前定義されたシンボルは次のとおりです。在预处理期间处理的
。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译日期
__TIME__ //文件被编译那一瞬的时间
__STDC__ //如果编译器遵循ANSI C(标准C),其值为1,否则未定义(报错)
例:
#include<stdio.h>
int main()
{
printf("%sn", __FILE__);
printf("%dn", __LINE__);
printf("%sn", __DATE__);
printf("%sn", __TIME__);
return 0;
}
操作結果:
ここで、VS は ANSI C (標準 C) を完全にはサポートしていないことに言及したいと思います。 gccgccグcc ANSI C (標準 C) をサポート
基本的な構文:
# define name stuff
例えば:
#define MAX 100
#define reg register // 为 register 这个关键字创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写 case 语句的时候自动吧 break 写上
//如果定义的 stuff 过长,可以分成几行写,除了最后一行外,每行的后面都加一个反斜杠(续行符)
#define DEBUG_PRINT printf("file:%stline:%dt
date:%sttime:%sn" ,
__FILE__,__LINE__ ,
__DATE__,__TIME__ )
- 2 番目の文は怠惰ですが、なぜですか?
- 3番目の文 のために のためにふまたは 円形
初始化、判断、调整都可以省略
, しかし、判定を省略した場合、判定条件は常に真であることを意味します。無限ループ- トラブルを引き起こしやすいため、4 番目のゲームではこれを行わないほうがよいでしょう。
- 5番目の文行継続文字その本質は分岐後のトラブルを防ぐことです。
转义
戻る回车符
, そのため、復帰は復帰ではなくなります。行継続文字の後には何も入力できません。“”
Enter キーを押すだけです。そうしないと、次のコード行には続きません。
ここで問題が発生します: # を使用してください 定義する 定義するdeふでe 識別子を定義する場合、最後に追加する必要がありますか?;
?
例えば:
#define MAX 1000
#define MAX 1000;
int main()
{
int n = MAX;
return 0;
}
上記のコードに加えて、;
、少し冗長に思えますが、プログラムの実行には影響しません。
追加するようです;
あるいは追加しないでください;
大丈夫でしょうか?
本当にそうなのか?
次の例を見てみましょう。
//例一
int main()
{
printf("%dn", MAX);
return 0;
}
//例二
int mian()
{
int max = 0;
if (1)
max = MAX;
else
max = 1;
return 0
}
交換後:
printf("%dn", 1000;);
印刷する1000;
どういう意味ですか?
if (1)
max = 1000;
;
else
max = 1;
他にelセ 誰と合わせる?
ほら、これには何か問題があるので、使用 # 定義する 定義するdeふでe インジケーターを定義するときは、インジケーターの後に追加しないでください。;
# 定義する 定義するdeふでe このメカニズムには次の条項が含まれています。允许把参数替换到文本中
、この実装はよく呼ばれます大きい ( マルコ ) ( マルコ )(まrco)または マクロを定義する (マクロを定義する) (マクロを定義する)(deふでeまクロ)
マクロと上記のマクロ定義識別子の違いは次のとおりです。マクロにはパラメータがあります
マクロの宣言方法は次のとおりです。
#define name(parament - list) stuff
それらの中の一つ パラメント パラメントp1つのr午前eんt - リスト リストl私st(パラメータリスト) は、以下に表示される可能性のあるシンボルのカンマ区切りリストです。 もの ものstあなたff 真ん中
注記: パラメント パラメントp1つのr午前eんt - リスト リストl私st(パラメータリスト)左括弧必ず一緒にいる 名前 名前ナムe の隣に、間に空白が存在する場合、引数リストは次のように解釈されます。 もの ものstあなたff の一部。
例:
//实现一个宏,计算一个数的平方
#define SQUARE(x) x*x
int main()
{
int a = 5;
int ret = SQUARE(a);
printf("%dn", ret);
return 0;
}
操作結果:
ご覧のとおり、5 の 2 乗は正しく計算されています。
しかし実際には、上記のコードには問題があります。次のコード スニペットを参照してください。
int a = 5;
printf("%dn", SQUARE(a + 1));
操作結果:
なぜそうなるのでしょうか? 5+1の結果は36と6です ∗ * ∗ 6 は 36 になるはずです。どうやって 11 を得たのですか?
問題はマクロにあることはわかっています宏是直接替换
の場合、上記のコードを直接置き換えた結果は次のようになります。
printf("%dn", a+1*a+1);
5 + 6 + 1、結果は当然 11
この問題は、マクロ定義の両側に括弧を追加することで簡単に解決できます。
#define SQUARE(x) (x)*(x)
では、この定義で問題はないのでしょうか?次のマクロ定義を見てみましょう。
#define DOUBLE(X) (X)+(X)
前の問題を回避するために定義内で括弧を使用しましたが、このマクロにより新たなエラーが発生する可能性があります。
int a = 5;
printf("%dn", 10 * DOUBLE(a));
操作結果:
出力結果は100ではなく55となります。理由は上記と同様です。 優先的な質問
解決:
#define DOUBLE(X) ((X)+(X))
要約すると、マクロを使用する場合括弧を決してケチらないでくださいマクロを使用するときに、パラメーター内の演算子または隣接する演算子間の予期しない相互作用を回避するため。
マクロ パラメータがマクロ定義内で複数回出現する場合、パラメータに副作用場合、このマクロを使用すると危険にさらされる可能性があり、その結果、不可预测
結果として。副作用は、式が評価されるときの永続的な効果です。
例えば:
x + 1; //不带副作用
x++; //带副作用
次の MAX マクロは、副作用のあるパラメーターによって引き起こされる問題を示しています。
#define MAX(a,b) ((a) > (b) ? (a):(b))
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf("x=%d, y=%d, z=%dn", x, y, z);
return 0;
}
操作結果:
なぜそうなるのでしょうか?一緒に分析しましょう
z = ((X++) > (y++) ? (x++) : (y++))
- まず判断を下します。 xxバツ++付き ええええ++判定、後置++なので判定する場合 xxバツ は5、 ええええ 8、8 > 5
- 審査後 xxバツ 6、 ええええ 9人分
- 次に実行します ええええ ++、接尾辞 ++ なので、結果は 9 になります。
- 続いて ええええ 自動インクリメントを実行し、 ええええ 最終結果は 10 です
私達はします xxバツ そして ええええ マクロに渡されると、特に結果が変わります。 ええええ、2回変更した後、あなたはひどくはないと言いました
副作用のあるパラメータがマクロに渡され、そのパラメータがマクロ内で複数回出現する場合、パラメータの副作用も複数回発生します。
プログラム # で展開 定義する 定義するdeふでe シンボルとマクロを定義するには、いくつかの手順が必要です
参数进行检查
# が含まれているかどうかを確認してください 定義する 定義するdeふでe 定義済み标识符
。その場合は、最初に置き換えられます被插入
マクロパラメータ名をその値で置き換えて、プログラム内の元の場所にコピーします。#define MAX(a,b) ((a) > (b) ? (a):(b))
#define M 10
int main()
{
int x = 5;
int z = MAX(x, M);
return 0;
}
上記のコードの MAX は # でも表されます 定義する 定義するdeふでe 定義済み大きい 。前回の検査でパラメータMが交換されており、今回交換することになりました。
MAX ( x , 10 ) MAX(x, 10)まあバツ(バツ,10) に置き換えられます ( ( x ) > ( 10 ) (( x ) > ( 10 )((バツ)>(10)
?
?
? ( x ) : ( 10 ) ) ( x ):(10))(バツ):(10))
確かに、宏里面嵌套宏
それもいいです
MAX(x, MAX(2, 3))
このとき、まずパラメータ内のマクロを置き換えてから、マクロ全体を置き換えます。
しかし、これに注意してください不是递归
、これは別のマクロへの引数として機能する単なるマクロです。递归是宏内部又调用了宏本身
。
また、プリプロセッサが # を検索するときも 定義する 定義するdeふでe シンボルを定義するときは、文字列定数の内容は検索されません
それはどういう意味ですか?栗をあげればわかります。
#define M 10
int main()
{
int x = 5;
int z = MAX(x, MAX(2, 3));
printf("M = %d", x);
return 0;
}
上記のコードではprintf("M = %d", x);
真ん中 んんま 10には置き換えられません
上記のマクロは、2 つの数値の大きい方の値を見つけるために使用されます。完全に関数として記述することができます。
int Max(int x, int y)
{
return x > y ? x : y;
}
それらはすべて同じ機能を達成することがわかりました。ただし、「2 つの数値のうち大きい方を見つける」という機能の場合、マクロを書くと、更有优势
いくつかの
理由は 2 つあります。
- のために使用される
调用函数
そして函数返回
のコードこの小さな計算を実際に実行するよりも時間がかかる場合があります (関数を呼び出すとき)スタックフレームを作成する )。したがって、マクロ比率関数はプログラム内にあります规模
そして速度
今まで一番- さらに重要なことには
函数的参数必须声明类型
これにより、関数は適切なタイプの式でのみ使用されます。それどころか、このマクロは多くの型に適用できます。整数、長整数、浮動小数点などを使用できます。
>
比べる。マクロのパラメータは、タイプに依存しないの。
将来的には常にマクロを使用するのでしょうか?実際、マクロは次の目的でのみ使用されます。簡単な計算、マクロと比較して、複雑で大規模な操作や関数には適していません。 短所:
- マクロが使用されるたびに、マクロ定義コードのコピーがプログラムに挿入されます。マクロが比較的短い場合を除き、
大幅度增加程序的长度
- マクロは
没法调试
の- マクロは型に依存しません。つまり、
不够严谨
- マクロにより操作の優先順位の問題が発生し、プログラムが
容易出错
しかし、関数ではできないことがマクロでできることもあります。
例えば:
int* p = (int*)malloc(10 * sizeof * (int));
私たちはこのように書くのは好きではありません マルロック マルロックまlloc 機能が面倒なのでやりたい大小
そして类型
渡してスペースを空ける
Malloc(10, int);
関数でこれができるのでしょうか?いや、だって関数は型を渡すことができません
マクロではできないので、マクロでもそれができますチェックしないでくださいあなたのパラメータタイプの
#define Malloc(n, type) (type*)malloc(n * sizeof(type))
int main()
{
int* p = Malloc(10, int);
return 0;
}
マクロと関数の比較:
属性 | # 定義する 定義するdeふでeマクロを定義する | 関数 |
---|---|---|
コード長 | 使用するたびに、非常に小さなマクロを除いて、プログラムにマクロ コードが挿入されるため、プログラムの長さは大幅に増加します。 | 関数コード値は 1 か所に表示され、関数が使用されるたびに、その場所にある同じコードが呼び出されます。 |
実行速度 | もっと早く | 関数の呼び出しと戻りのオーバーヘッド (スタック フレームを開く) が追加されるため、遅いものから始めましょう。 |
演算子の優先順位 | マクロ パラメーターは、周囲のすべての式のコンテキストで評価されます。括弧が含まれていない場合、隣接する演算子の優先順位によって予期せぬ結果が生じる可能性があるため、マクロをより多くの括弧で記述することをお勧めします。 | 関数パラメーターは、関数が呼び出されたときに 1 回だけ評価され、その結果値が関数に渡されるため、式の評価結果がより予測しやすくなります。 |
副作用のあるパラメータ | パラメータはマクロ内の複数の位置に置換される可能性があります。マクロのパラメータが複数回評価される場合、副作用のあるパラメータ評価により予期しない結果が生じる可能性があります。 | 関数のパラメーターはパラメーターを渡すときに 1 回だけ呼び出されるため、結果の予測が容易になります。 |
パラメータの種類 | マクロのパラメータは、パラメータの操作が正当である限り、どのタイプのパラメータでも使用できます。 | 関数のパラメーターは型に関連しています。パラメーターの型が異なる場合は、同じタスクを実行する場合でも、異なる関数が必要になります。 |
デバッグ | マクロはデバッグに不便です | 関数は段階的にデバッグ可能 |
再帰 | マクロは再帰的にはできません | 関数は再帰的に使用できます |
それぞれの利点を組み合わせる方法はありますか?
C++で導入インライン関数 インライン インラインでlでe ——マクロと関数の両方の利点を兼ね備えています
マクロと同じくらい高速に実行されますが、関数と同じ効果があります。