Detailed explanation of macros in C language (super detailed!)

Table of contents

1. Notes before using macros - #define related knowledge

        General structure:

         Complements to the predefined symbols:

2. Define macros with #define

        What are macros?

        Replacement rules for #define:

3. Commonly used macro definitions

1. Macro definition constant

2. Define a macro statement

3. Macro definition function

        Comparison of macros and functions:

4. # and ## respectively stringify and connect two symbols into one symbol 

#stringify

 ## Concatenate two symbols into one symbol

4. Function symbols related to macros

1. Newline character '\'

2. Cancel macro definition #undef 

5. Naming convention


1. Notes before using macros - #define related knowledge

        General structure:

#define    name    stuff

         自定义名    内容

        chestnut:

#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;
}

         


         Complements to the predefined symbols:

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

2. Define macros with #define

        What are macros?

        A macro can be seen as a collection of commands. It is a preprocessor directive that replaces the macro name with the following substitution during the precompilation phase.

        And #define can be used to define macros:

        The #define mechanism includes a provision that allows parameters to be substituted into the text, and this implementation is often called a macro or define macro.

        The declaration of the macro is:

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

        chestnut:

        Implement a square root macro        

#define SQ(x) x*x

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

        His actual execution structure is 7*7-> is 49

        Or use this macro we just defined

        We execute the following piece of code:       

int a=6;

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

        His actual execution structure is 6+1*6+1-> is 13

        This shows what? This confirms that the macro mentioned above replaces the parameters into the text , that is, the macro directly replaces x with 6+1 and directly brings it into the following expression!

        In this regard, according to our original intention. At this point we can use parentheses to solve this problem:

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

        This gives us a reminder: we'd better use more parentheses when using macros, so as to avoid unnecessary mistakes!

Look at another chestnut:

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

        In this example we used parentheses for this macro, at first glance the output of this example looks like 100

        But what about reality? Pictured above!

      

Let's see how it actually performs, it performs the replacement operation as:

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

        So we say that you need to use more parentheses when defining macros!

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

        Change it to this to achieve the desired effect!


        Replacement rules for #define:

There are several steps involved when         expanding #defines to define symbols and macros in a program :
1. When calling a macro, first check the parameters to see if they contain any symbols defined by #define . If yes, they are replaced first.
2. The replacement text is then inserted into the program in place of the original text. For macros, parameter names are replaced by their values.
3. Finally, the resulting file is scanned again to see if it contains any symbols defined by #define . If yes, repeat the above processing.
        Notice:
1. Symbols defined by other #defines can appear in macro parameters and #define definitions. But with macros, recursion cannot occur.
2. When the preprocessor searches for symbols defined by #define , the content of the string constant is not searched.

3. Commonly used macro definitions

1. Macro definition constant

         Defines constants such as strings, integers, floats, etc.

        chestnut:

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

       


2. Define a macro statement

        chestnut:

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

3. Macro definition function

        Macros can take arguments, just like real functions. The specific method of accepting parameters is similar to that of functions, except that there is no need to specify the function type, which is also an advantage of macro-defined functions! For example: when I define a function, sometimes I need to pass an integer, and sometimes I need to pass a floating point type. The function may need to define several more according to the type, but the macro only needs one!

        Chestnut 1:

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

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

       

        Chestnut 2:

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

        In this example, functions cannot achieve the same effect as macros , so why do we need to define macros when we have functions? This is an obvious example.


        Comparison of macros and functions:


4. # and ## respectively stringify and connect two symbols into one symbol 

#stringification _

        This is easy to understand and just look at the example!

        chestnut:

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

      


 ## Concatenate two symbols into one symbol

        ## You can combine the symbols on both sides of it into one symbol. It allows macro definitions to create identifiers from separated text fragments.

        chestnut:

#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. Function symbols related to macros

1. Newline character '\'

        Add "\" at the end of each line (except the last line), which means newline . The purpose of this is to prevent code redundancy. If the code is crowded in one paragraph, the code will not be beautiful and the readability will not be good.

        chestnut:

#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. Cancel macro definition #undef 

        This command is used to remove a macro definition.        

#define SORT 1000
#undef SORT

        After #undef SORT is equivalent to no definition, invalid . If you use it again, you will report an error!


5. Naming convention

        Careful friends may have discovered it! When I defined the macro, I used capital letters as its custom name!

        This is because there is a default naming convention for this:

        In general, the usage syntax of function macros is very similar. So language itself cannot help us distinguish between the two.

        Then one of our usual habits is:

        capitalize macro names

        Do not use all uppercase function names                                     


       Thank you for your patience to see here ღ( ´・ᴗ・` ) to compare your heart, if there is any mistake, please kick the author o(╥﹏╥)o!

Guess you like

Origin blog.csdn.net/weixin_64038246/article/details/131850405
Recommended