1

Summary

1) #define is one of the unit entities processed by the preprocessor text replacement is performed during the pre-compilation period

2) #define can appear anywhere in the program , and the code after the definition can be used

3) #define can define macro constants, which are essentially literals

4) define can define an expression, use the similar function ; function may be more powerful (type can be used as a parameter, find the size of the array); more error-prone (when mixed with other operations)

5) Since the macro is a direct text replacement, does not have any call overhead cannot be recursive in the macro expression; the macro is processed by the preprocessor, so the compiler does not know the existence of the macro, and naturally, the macro does not have any The concept of scope is for variables and functions.

6) Commonly used predefined macros

MacromeaningExample
__FILE__File name to be compiledfile1.c
__LINE__Current line number25
__DATE__Compile dateJan 31 2012
__TIME__Compile time17:01:01
__STDC__Does the compiler follow the standard C specification1

Macro definition and usage analysis

#define is one of the unit entities processed by the preprocessor
#define can appear anywhere in the program
The code after the definition of #define

1. Macro constants defined by #define

#define can be used directly, the essence is literal (will not occupy memory, string literal will be stored in read-only storage area)

// test.c中 下面的宏定义正确么?
#define ERROR -1
#define PATH1 "D:\test\test.c"
#define PATH2 D:\test\test.c
#define PATH3 D:\test\
test.c

int main()
{
    int i = ERROR;
    char* p1 = PATH1;
    char* p2 = PATH2;
    char* p3 = PATH3;
    return 0;
}
单步编译
gcc -E test.c -o test.i    ==> 预编译,生成中间文件.i
gcc -S test.i -o test.s    ==> 编译,生成汇编文件.s

Analysis: In the first pre-compilation stage, the define is processed and the .i file is generated. There will be no error at this time; in the next compilation stage, when the intermediate file is converted to an assembly file, an error will be reported.
image.png
The reason is: in the , only text replacement is performed, without syntax checking; when the compile stage, the grammar check is performed on the replaced .i file, and then the assembly file is generated. At this time, the syntax check is wrong.
image.png

2. #define defined expression

#define expressions similar function calls
#define expressions can be more powerful than functions
#define Expressions are more error-prone than functions

#define SUM(a, b) (a) + (b)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define DIM(a) sizeof(a) / sizeof(*a)

int main()
{
    int a = 1;
    int b = 3;
    int c[2] = {0};

    // expected: 4, 1, 2
    printf("SUM(a, b) = %d\n", SUM(a, b));
    printf("MIN(a, b) = %d\n", MIN(a, b));
    printf("size of array = %d\n", DIM(c));

    // unexpected: 3
    printf("unexpected: %d", MIN(++a, b));   // 期望得到++a和b中的较小的值:2
    return 0;
}

analyze:

  • The define expression similar to a function call. Like the above example, the definition of a macro in printf is very much like a function call.
  • The define expression may be more powerful than the function. As above, the DIM macro can find the size of the array, cannot find the size of an array through the function in the C language, because degenerates into a pointer when the array is used as a function parameter. ; For another example, C language cannot take type as a parameter, but macros can.
  • The define expression more error-prone. As above, the expected value of MIN(++a, b) is 2, but the actual value is 3. From the result of single-step compilation, it can be seen that the expression after replacement is ((++a) < (b) ? (++b) : (b)) , and the preceding ++ is executed twice, so 3 is obtained. pre-compiler is like a microphone. In the process of transmitting, there is ambiguity.

The macro expression is preprocessor, and the compiler does not know the existence of the macro;
Macro expressions use "actual parameters" to completely replace formal parameters, and does not perform any operations;
The macro expression does not have any call overhead: (because the text replacement is directly performed, unlike functions that require parameters such as stacking, returning, etc.)
Recursive definitions cannot appear in macro expressions: (because the macro only performs one during the preprocessing period, and subsequent symbol compilers will not recognize it)

#define SUM(n) ((n>0) ? (SUM(n-1) + n) : 0)
int s = SUM(10);    // 编译的时候就会报错,undefined reference SUM

3. Does the constant or expression defined by the macro have scope restrictions?

下面的程序合法么?
void def()
{
    #define PI 3.1415926
    #define AREA(r) r*r*PI
}
double area(double r)
{
    retrun AREA(r);
}

int main()
{
    double r = area(10);
    return 0;
}

Analysis: There will be no errors in compiling and running. Explain that the macro has no scope restriction. As long as the definition is complete, the following code can be used. If used before the definition, an undefined reference error will be reported. scope of 161c33d7c22d21 is only for variables and functions. The macro is expanded during the preprocessing period. is no macro in 161c33d7c22d22 at the compile time, so there is no way to limit the scope of the macro.

4. Commonly used predefined macros

MacromeaningExample
__FILE__File name to be compiledfile1.c
__LINE__Current line number25
__DATE__Compile dateJan 31 2012
__TIME__Compile time17:01:01
__STDC__Does the compiler follow the standard C specification1

This article is summarized from "C Language Advanced Course" by Tang Zuolin from "Ditai Software Academy".
If there are any errors or omissions, please correct me.


bryson
169 声望12 粉丝