2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
C language sets somePredefined symbols, can be used directly, the predefined symbols are在预处理期间处理的
。
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译日期
__TIME__ //文件被编译那一瞬的时间
__STDC__ //如果编译器遵循ANSI C(标准C),其值为1,否则未定义(报错)
Example:
#include<stdio.h>
int main()
{
printf("%sn", __FILE__);
printf("%dn", __LINE__);
printf("%sn", __DATE__);
printf("%sn", __TIME__);
return 0;
}
operation result:
Just to mention here, VS does not fully support ANSI C (standard C);
g
c
c
gcc
gcc Support for ANSI C (Standard C)
Basic syntax:
# define name stuff
for example:
#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__ )
- The second sentence is laziness, what's wrong?
- The third sentence f o r for for Circular
初始化、判断、调整都可以省略
, but if the judgment is omitted, it means that the judgment condition is always true, that is,Infinite loop- It's best not to do this in the fourth game, it's easy to get into trouble
- Fifth sentenceLine continuation characterIt is to prevent problems after branching. Its essence is
转义
Back回车符
, so that the carriage return is no longer a carriage return. There should be nothing after the line continuation character. Press“”
Press Enter directly, otherwise the next line of code will not be continued
Now the question is: using #
d
e
f
i
n
e
define
define When defining an identifier, should we add;
?
for example:
#define MAX 1000
#define MAX 1000;
int main()
{
int n = MAX;
return 0;
}
The above code plus;
, it seems a bit redundant, but it has no effect on the program operation
It seems to add;
Or without;
It will be all right?
is it really like this?
Let’s look at the following example:
//例一
int main()
{
printf("%dn", MAX);
return 0;
}
//例二
int mian()
{
int max = 0;
if (1)
max = MAX;
else
max = 1;
return 0
}
After replacement:
printf("%dn", 1000;);
Print1000;
What means?
if (1)
max = 1000;
;
else
max = 1;
e
l
s
e
else
else Who to match?
You see, this is the problem, right?use #
d
e
f
i
n
e
define
define When defining an identifier, do not add;
#
d
e
f
i
n
e
define
define The mechanism includes a provision that允许把参数替换到文本中
, this implementation is usually calledMacro
(
m
a
r
c
o
)
(marco)
(marco)or Defining Macros
(
d
e
f
i
n
e
m
a
c
r
o
)
(define macro)
(definemacro)
The difference between the macro and the macro definition identifier above is:Macros have parameters
Here is how the macro is declared:
#define name(parament - list) stuff
one of them
p
a
r
a
m
e
n
t
parament
parament -
l
i
s
t
list
list(Parameter list) is a comma-separated list of symbols that may appear in
s
t
u
f
f
stuff
stuff middle
Note:
p
a
r
a
m
e
n
t
parament
parament -
l
i
s
t
list
list(parameter list)Left parenthesisMust be with
n
a
m
e
name
name Close toIf there is any whitespace between them, the argument list is interpreted as
s
t
u
f
f
stuff
stuff a part of.
Example:
//实现一个宏,计算一个数的平方
#define SQUARE(x) x*x
int main()
{
int a = 5;
int ret = SQUARE(a);
printf("%dn", ret);
return 0;
}
operation result:
As you can see, the square of 5 is calculated correctly.
But in fact the above code is problematic, please see the following code segment:
int a = 5;
printf("%dn", SQUARE(a + 1));
operation result:
Why is this so? 5+1 equals 36, while 6 ∗ * ∗ 6 should be 36, how did 11 come about?
The problem is with the macro, we know宏是直接替换
The result of directly replacing the above code is:
printf("%dn", a+1*a+1);
5 + 6 + 1, the result is 11.
We add brackets on both sides of the macro definition, and this problem is easily solved
#define SQUARE(x) (x)*(x)
Is there no problem with this definition? Let's take a look at the following macro definition
#define DOUBLE(X) (X)+(X)
We used parentheses in the definition to avoid the previous problem, but this macro may cause new errors.
int a = 5;
printf("%dn", 10 * DOUBLE(a));
operation result:
The output result is not 100 but 55. The reason is similar to the above. The question of priority
Solution:
#define DOUBLE(X) ((X)+(X))
In summary, when using macrosDon't skimp on bracketsto avoid unexpected interactions between operators or adjacent operators in the arguments when using macros.
When a macro parameter appears more than once in the macro definition, if the parameter hasside effect, then you may be in danger when using this macro, resulting in不可预测
A side effect is a permanent effect that occurs when an expression is evaluated.
For example:
x + 1; //不带副作用
x++; //带副作用
The following code example of the MAX macro demonstrates the problem caused by parameters with side effects:
#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;
}
operation result:
Why is this happening? Let’s analyze it together.
z = ((X++) > (y++) ? (x++) : (y++))
- First, make a judgment: x x x++ and y y y++ judgment, because it is postfix ++, when judging x x x is 5, y y y is 8, 8 > 5
- After judging x x x is 6, y y y For 9
- Then execute y y y ++, because it is postfix++, the result is 9
- Next y y y To auto-increment, y y y The final result is 10
we will
x
x
x and
y
y
y When passed into a macro, the output has changed, especially
y
y
yAfter two changes, do you think it is scary?
When a parameter with side effects is passed to a macro, and the parameter appears more than once in the macro, the side effects of the parameter will also be more than once.
Extending in Programs# d e f i n e define define When defining symbols and macros, several steps are involved
参数进行检查
, see if it contains #
d
e
f
i
n
e
define
define Defined标识符
If so, they are replaced first被插入
To the original location in the program, the macro parameter names are replaced by their values#define MAX(a,b) ((a) > (b) ? (a):(b))
#define M 10
int main()
{
int x = 5;
int z = MAX(x, M);
return 0;
}
In the above code, MAX is also represented by #
d
e
f
i
n
e
define
define DefinedMacroIn the last test, its parameter M has been replaced. This time it is time to replace it.
M
A
X
(
x
,
10
)
MAX(x, 10)
MAX(x,10) Replaced by
(
(
x
)
>
(
10
)
((x) > (10)
((x)>(10)
?
?
?
(
x
)
:
(
10
)
)
(x):(10))
(x):(10))
certainly,宏里面嵌套宏
it is also fine
MAX(x, MAX(2, 3))
At this time, first replace the macro in the parameter, and then replace the entire macro
But it should be noted that this不是递归
, which is just a macro as an argument to another macro.递归是宏内部又调用了宏本身
。
Also, when the preprocessor searches for #
d
e
f
i
n
e
define
define When defining symbols,The contents of string constants are not searched.
What does it mean? Let me give you an example.
#define M 10
int main()
{
int x = 5;
int z = MAX(x, MAX(2, 3));
printf("M = %d", x);
return 0;
}
In the above codeprintf("M = %d", x);
middle
M
M
M It will not be replaced by 10
The above macro to find the larger value of two numbers can be written as a function
int Max(int x, int y)
{
return x > y ? x : y;
}
We found that they can all perform the same function. However, for the function of "finding the larger value of two numbers", it would be more difficult to write it as a macro.更有优势
Some
There are two reasons:
- Used for
调用函数
and函数返回
ofCodeIt may take more time than actually performing the small computation (calling the functionCreate a stack frame). Therefore, macros are more important than functions in a program.规模
and速度
Better than- More importantly
函数的参数必须声明类型
, which means that the function can only be used on expressions of the appropriate type. On the contrary, this macro can be used for multiple types: integers, long integers, floating point types, etc.
>
to compare.The macro parameters areType-agnosticof。
So will we all use macros in the future? Actually, macros are only used inSimple calculationIt is not suitable for complex and large operations and functions compared to macros. Disadvantages:
- Each time you use a macro, a copy of the macro definition code is inserted into your program. Unless your macro is short, this may
大幅度增加程序的长度
- Macros are
没法调试
of- Since macros are type-independent,
不够严谨
- Macros may cause operation priority problems, causing the program
容易出错
But sometimes, macros can do things that functions can't do.
For example:
int* p = (int*)malloc(10 * sizeof * (int));
We hate writing like this
m
a
l
l
o
c
malloc
malloc The function is too complicated. I want to大小
and类型
Pass it over to open up space
Malloc(10, int);
Can a function do this? No, becauseFunctions cannot pass types
Macros can do this, because macros are notNo inspectionYour parameterstypeof
#define Malloc(n, type) (type*)malloc(n * sizeof(type))
int main()
{
int* p = Malloc(10, int);
return 0;
}
A comparison between macros and functions:
Attributes | # d e f i n e define defineDefining Macros | function |
---|---|---|
Code length | Each time a macro is used, it is inserted into the program, and except for very small macros, the program length can grow substantially. | The function code value appears in one place, and each time the function is used, the same code in that place is called |
Execution speed | Faster | There is additional overhead for calling and returning functions (opening stack frames), so |
Operator precedence | Macro parameters are evaluated in the context of all surrounding expressions. Unless parentheses are added, the precedence of adjacent operators may have unpredictable consequences. Therefore, it is recommended to use more parentheses when writing macros. | Function parameters are evaluated only once when the function is called, and their result value is passed to the function, making the evaluation result of the expression easier to predict. |
Parameters with side effects | Parameters may be substituted into multiple locations within a macro. If a macro's parameters are evaluated multiple times, parameter evaluation with side effects may produce unpredictable results. | Function parameters are only called once when passing them, and the results are more predictable |
Parameter Type | The parameters of the macro are independent of type. As long as the operation on the parameters is legal, it can be used for any parameter type. | Function parameters are type-dependent. If the types of the parameters are different, different functions are required, even if they perform the same task. |
debug | Macros are not easy to debug | Functions can be debugged line by line |
recursion | Macros cannot be recursive | Functions can be recursive |
Is there any way to combine their advantages?
Introduced in C++Inline functions
i
n
l
i
n
e
inline
inline —— It has the advantages of both macros and functions
It executes as fast as a macro, but has the same effect as a function.