2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
In the previous issue【C language】—— Detailed explanation of preprocessing (Part 2)In the study of , we introduced the relevant knowledge of macro in preprocessing in detail, I believe everyone has gained a lot. Don't worry, let's continue to learn other knowledge about preprocessing in this issue.
# 运算符
Converts a macro argument to a string literal. It is only allowed to appear in the replacement list of a macro that takes an argument.# 运算符
The operation performed can be understood as "stringification"
What does that mean?
Let's lay the groundwork first:
int mian()
{
printf("hello" "worldn");
printf("helloworldn");
return 0;
}
What is the difference between the above two codes? Let's take a look:
You can see that the effect of two strings and one string is the same.C语言会把两个字符串天然连成一个字符串
, adding a space in the middle doesn't help either.
Now there is such a scene:
int main()
{
int a = 1;
printf("The value of a is %dn", a);
int b = 20;
printf("The value of b is %dn", b);
float f = 8.5f;
printf("The value of f is %fn", f);
return 0;
}
We found that the logic of the three codes is very相像
Yes, but there are些许不同
。
So we thought, since they are so similar, can we封装成一个函数
, for easy use?
But the function can't do this.
then what should we do?
We can try to solve it with macros.
#define Print(n, format) printf("The value of n is " format "n", n)
int main()
{
int a = 1;
Print(a, "%d");
//printf("The value of a is %dn", a);
int b = 20;
Print(b, "%d");
//printf("The value of b is %dn", b);
float f = 8.5f;
Print(f, "%f");
//printf("The value of f is %fn", f);
return 0;
}
operation result:
we discover
n
n
n It has not changed, so how should I modify it?
This is where our # operator comes in handy:# Converts a macro argument toString literals,Right now
n
n
n become
“
n
”
“n”
“n”
At this time, we can use the splicing method to make it
#define Print(n, format) printf("The value of " #n " is " format "n", n)
Don’t understand? Read the explanation below and you will understand.
##
You can put it in hisThe symbols on both sides are combined into one symbol, which allows macro definitions从分离的文本片段创建标识符
。##
is calledMarking adhesiveSuch a connection must produce a合法
The result is undefined otherwise.
As we said before, to write a function that finds the larger value of two numbers, we need to write different functions for different data types.
int int_max(int x, int y)
{
return x > y ? x : y;
}
float float_max(float x, float y)
{
return x > y ? x : y;
}
This is inevitably too cumbersome, and there are many similarities between the two functions.
Is there a way to quickly create such a function?MouldSame, just apply a function and it will come out
We can write a宏
:
#define GENERIC_MAX(type)
type type##_max(type x, type y)
{
return x > y ? x : y;
}
#define GENERIC_MAX(type)
type type##_max(type x, type y)
{
return x > y ? x : y;
}
GENERIC_MAX(int); //相当于定义了一个函数int_max
GENERIC_MAX(float); //相当于定义了一个函数float_max
int main()
{
int r1 = int_max(3, 5);
printf("%dn", r1);
float r2 = float_max(2.3f, 7.6f);
printf("%fn", r2);
return 0;
}
operation result:
We can also
g
c
c
gcc
gcc Observe the pre-processed.i
Files, have a more intuitive understanding
Of course, the function generated in this way is not convenient for debugging
That here ##
What is its function?
add ##
, the compiler will think they are a symbol
Let's take a look at##
Effect:
Generally speaking, the syntax of functions and macros is very similar, so语言本身没法帮我们区分二者
One of our usual habits is:
- Name the macroAll caps
- Function nameDon't capitalize
Of course, these naming rules are not absolute.
for example
o
f
f
s
e
t
offset
offset This macro is written in all lowercase
Note:
o
f
f
s
e
t
offset
offset It is used to calculate the offset of the structure members relative to the starting position of the structure
# u n d e f undef undef Instructions forRemove a macro definition
The above code uses in line 169#
u
n
d
e
f
undef
undef Removed the MAX macro. It works fine when the 168th line is called before the removal, but an error occurs when the 170th line is called after the removal.
Many C compilers (not including VS) provide a capability to allow symbols to be defined on the command line.
For example: This feature is useful when we want to compile different versions of a program based on the same source file. (Suppose a program declares an array of a certain length. If the machine has limited memory, we need a very small array, but if another machine has more memory, we need a larger array.)
The command line definition isPreprocessing stageIn the preprocessing stage, the above code s z sz sz The value of has been determined
When compiling a program, it is very important to compile or discard a statement (or a group of statements).方便
Because we can useConditional compilation directives
The conditional compilation directive is this code我想让你编译就编译,不想让你编译你就不要编译了
We can set a condition for it. If the condition is true, this code will be compiled. If the condition is false, this code will not be compiled.
For example:
Some debugging code is a pity to delete, but it is troublesome to keep it, so we can compile it selectively
Commonly used conditional compilation instructions:
#if 常量表达式
//···
#endif
#if 常量表达式
//···
#elif 常量表达式
//···
#else
//···
#endif
Whichever statement is true, execute that statement
#define M 1
int main()
{
#if M == 0
printf("hellon");
#elif M == 1
printf("worldn");
#elif M == 2
printf("csdnn");
#endif
printf("886n");
return 0;
}
#if defined(symbol)
#ifdef symbol
//上面两个的反面
if !defined(symbol)
#ifndef symbol
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif
# include "filename"
Search strategy: FirstThe project directory where the source files are locatedIf the header file is not found, the compiler searches for it in the same way as it searches for a library function header file.Standard location searchhead File
If you can't find it,Compile Error
L
i
n
u
x
Linux
Linux The standard header file path for the environment (where the header files are placed):
/usr/include
Standard header file path for VS environment:
C:Program Files (x86)Microsoft Visual Studio 12.0VCinclude
//这是VS2013的默认路径
#include <filename.h>
Find the header file directlyStandard PathGo down and search, if you can't find it, it will promptCompile Error。
Can we say that we can also use it for library files?“ ”
The form includes
the answer isaffimBut this is how to findRelatively low efficiencyOf course, this is alsoNot easy to distinguishIs it a library file or a local file?
After studying the previous (compile and link), we know that the header file is included in the preprocessing stage.直接将该文件的代码拷贝到包含头文件的地方
If a header file is included 10 times, it is actually compiled 10 times. If it is included repeatedly, the pressure on compilation will be greater.
t e s t . c test.c test.c
#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
int main()
{
return 0;
}
t e s t . h test.h test.h
void test();
struct Stu
{
int id;
char name[20];
};
But in a project, a file is inevitably included multiple times, so how to solve this problem?
Answer:Conditional compilation
#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif
How do you understand it?
- Should we compile the header file when we include it for the first time?Make a judgment first
- The symbol __TEST_H__ does notNot defined,wantCompile
- NextDefine the __TEST_H__ symbol
- After including the header file again, I found __TEST_H__Defined,no longerFor the header file included laterCompile
However, the above writing method is more troublesome, there is another way to write it:
#pragma once
The effect is the same as above.
This avoids repeated import of header files
#error
#pragma
#line
···
#pragma pack()//在结构体部分介绍
Interested friends can read "In-depth Analysis of C Language"
Well, this is the end of this article about preprocessing. I hope this blog can help you. At the same time, if there are any mistakes, please correct me. Let us make progress together on the road of learning C language!