C言語でマクロを詳しく解説(超詳しい!)

目次

1. マクロを使用する前の注意事項 - #define 関連知識

        一般的な構造:

         事前定義されたシンボルの補足:

2. #define でマクロを定義する

        マクロとは何ですか?

        #define の置換ルール:

3. よく使用されるマクロ定義

1. マクロ定義定数

2. マクロステートメントを定義する

3. マクロ定義機能

        マクロと関数の比較:

4. # と ## はそれぞれ 2 つのシンボルを文字列化し、1 つのシンボルに接続します 

#stringify

 ## 2 つのシンボルを 1 つのシンボルに連結します

4. マクロに関する関数記号

1. 改行文字「\」

2. マクロ定義#undefを解除 

5. 命名規則


1. マクロを使用する前の注意事項 - #define 関連知識

        一般的な構造:

#define    name    stuff

         自定义名    内容

        栗:

#define OP 256
#define YU "youarewelcome"
#define S(r) (r*r)
#define REG register          //为 register这个关键字,创建一个简短的名字
#define PRINT printf("file:%s line:%d\n", __FILE__, __LINE__)//__FILE__,__LINE__这是个啥?别急后面有补充!

#include<stdio.h>
int main()
{
	printf("%d \n", OP);
	printf("%s \n",YU);
	printf("%d \n", S(6));
	PRINT;
	return 0;
}

         


         事前定義されたシンボルの補足:

__FILE__      //进行编译的源文件 
__LINE__     //文件当前的行号 
__DATE__    //文件被编译的日期 
__TIME__    //文件被编译的时间 
__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

2. #define でマクロを定義する

        マクロとは何ですか?

        マクロはコマンドの集合として見ることができます。これは、プリコンパイル段階でマクロ名を次の置換に置き換えるプリプロセッサディレクティブです。

        #define を使用してマクロを定義できます。

        #define メカニズムには、パラメーターをテキストに置換できるようにする機能が含まれており、この実装はマクロまたは定義マクロと呼ばれることがよくあります。

        マクロの宣言は次のとおりです。

  #define name( parament-list ) stuff
//其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中

        栗:

        平方根マクロを実装する        

#define SQ(x) x*x

printf("%d \n", SQ(7));

        彼の実際の実行構造は 7*7 -> は 49

        または、先ほど定義したこのマクロを使用します

        次のコードを実行します。       

int a=6;

printf("%d \n", SQ(6+1));

        彼の実際の実行構造は 6+1*6+1 -> は 13

        これは何を示していますか? これは、上記のマクロがパラメータを text に置き換えていること、つまり、マクロが x を 6+1 に直接置き換え、それを次の式に直接取り込んでいることを確認します。

        この点に関しては、当初の意図どおりです。この時点で、括弧を使用してこの問題を解決できます。

#define SQ(x) (x)*(x)

        これは、不要な間違いを避けるために、マクロを使用するときはより多くの括弧を使用することをお勧めします。

別の栗を見てください

#define DOUBLE(x) (x) + (x) 
int a = 5; 
printf("%d\n" ,10 * DOUBLE(a));

        この例では、このマクロに括弧を使用しました。一見すると、この例の出力は 100 のように見えます。

        しかし、現実はどうでしょうか?上の写真です!

      

実際にどのように実行されるかを見てみましょう。置換操作は次のように実行されます。

printf ("%d\n",10 * (5) + (5));

        したがって、マクロを定義するときは、より多くの括弧を使用する必要があると言えます。

#define DOUBLE( x)   ( ( x ) + ( x ) )

        希望の効果を得るには、これを変更してください。


        #define の置換ルール:

        #defines を展開してプログラム内のシンボルとマクロを定義する 場合は、いくつかの手順が必要です。
1. マクロを呼び出すときは、まずパラメータをチェックして、 #defineで 定義されたシンボルが含まれているかどうかを確認します。「はい」の場合、最初に置き換えられます。
2. 置換テキストは、元のテキストの代わりにプログラムに挿入されます。マクロの場合、パラメータ名はその値に置き換えられます。
3. 最後に、結果のファイルが再度スキャンされ、 #defineで 定義されたシンボルが含まれているかどうかが確認されます。「はい」の場合は、上記の処理を繰り返します。
        知らせ:
1.他の #defineで定義されたシンボルは、 マクロ パラメーターおよび #define定義 に出現できます。 しかし、マクロでは再帰は発生しません。
2. プリプロセッサが #define で定義されたシンボルを検索する場合、文字列定数の内容は検索されません。

3. よく使用されるマクロ定義

1. マクロ定義定数

         文字列、整数、浮動小数点などの定数を定義します。

        栗:

#define AO 114514
#define NTR "我可太喜欢了"
#define KK 3.14
#include<stdio.h>
int main()
{
	printf("%d %s %f", AO, NTR, KK);
	return 0;
}

       


2. マクロステートメントを定義する

        栗:

#include<stdio.h>
#define PFINT printf("hello world!\n");
int main()
{
	PFINT///预处理时会被替换为 printf("hello world!\n");
	return 0;
}

3. マクロ定義機能

        マクロは実際の関数と同様に引数を取ることができます。パラメーターを受け入れる具体的な方法は、関数の種類を指定する必要がないことを除けば関数の方法と似ています。これはマクロ定義関数の利点でもあります。例: 関数を定義するとき、整数を渡す必要がある場合もあれば、浮動小数点型を渡す必要がある場合もあります。関数は型に応じてさらにいくつか定義する必要があるかもしれませんが、マクロに必要なのは 1 つだけです。

        栗1:

#define MAX(a, b) ((a)>(b)?(a):(b))
#include<stdio.h>

int main()
{
	printf("%d", MAX(114, 514));
	return 0;
}

       

        栗2:

#define MALLOC(num, type)\ 
(type *)malloc(num * sizeof(type)) //这和\是干啥的?详见地四大点\的作用
... 
//使用 
MALLOC(10, int);//类型作为参数 
//预处理器替换之后: 
(int *)malloc(10 * sizeof(int)); 

        この例では、関数はマクロと同じ効果を実現できません。では、関数があるのになぜマクロを定義する必要があるのでしょうか? これは明らかな例です。


        マクロと関数の比較:


4. # と ## はそれぞれ2 つのシンボルを文字列化し1 つのシンボルに接続します 

#stringify _

        これは理解しやすいので、例を見てください。

        栗:

#define STR(exp) printf("%s\n",#exp);
#include<stdio.h>
int main()
{
	STR(for fun)
	return 0;
}

      


 ## 2 つのシンボルを 1 つのシンボルに連結します

        ## 両側のシンボルを 1 つのシンボルに結合できます。これにより、マクロ定義で分離されたテキストの断片から識別子を作成できます。

        栗:

#include<stdio.h>
#define ADD_TO(num, value) num##value


int main()
{
	int a = ADD_TO(114, 514);
	printf("%d \n", a);
	return 0;
}

       


4. マクロに関する関数記号

1. 改行文字「\」

        各行の末尾に「\」を追加します (最後の行を除く)。これは newline を意味しますこれはコードの重複を防ぐためで、一つの段落にコードが密集しているとコードが美しくなくなり、可読性も悪くなります。

        栗:

#include<stdio.h>
#define PFINT printf("hello world!\n");\
			  printf("goodbye world!\n");
#define NUM 1,\
			2,\
			3
int main()
{
	PFINT
	int x[] = { NUM };//->int x[] = { 1,2,3 };
	printf("%d %d %d \n", x[0], x[1], x[2]);
	return 0;
}

       


2. マクロ定義#undefを解除 

        このコマンドはマクロ定義を削除するために使用されます。        

#define SORT 1000
#undef SORT

        #undef の後、SORT は定義なし、無効に相当します再度使用すると、エラーが報告されます。


5. 命名規則

        用心深い友人が発見したかもしれません。マクロを定義するときに、カスタム名として大文字を使用しました。

        これは、次のようなデフォルトの命名規則があるためです。

        一般に、関数マクロの使用構文は非常に似ています。したがって、言語自体はこの 2 つを区別するのに役立ちません。

        そして、私たちのいつもの習慣の1つは次のとおりです。

        マクロ名を大文字にする

        すべて大文字の関数名を使用しないでください                                     


       ここまでご覧いただきありがとうございますღ( ´・ᴗ・` )心比べて、間違いがあれば作者を蹴ってくださいo(╥﹏╥)o!

おすすめ

転載: blog.csdn.net/weixin_64038246/article/details/131850405
おすすめ