preface
C execution process 1, compilation: the formation of object code 2, link: the object code and C function library link, merge the code, generate executable files. 3, run,
Example:
Test.txt
printf("I love coding\n");
Copy the code
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(a){
// Precompile: Copy the complete code of the file directly in preparation for compilation (replace)
// Before compiling, do something
//#include "test.txt" equals printf("I have a Dream.");
#include "Test.txt"
getchar(a);return 0;
}
Copy the code
Result output:
I love coding
Copy the code
C preprocessor
The C preprocessor is not part of the compiler, but it is a separate step in the compilation process. In short, the C preprocessor is nothing more than a text-replacement tool that instructs the compiler to do the required preprocessing before the actual compilation. We will abbreviate the C Preprocessor to CPP. All preprocessor commands begin with a pound sign (#). It must be the first non-null character, and for readability, preprocessor instructions should start from the first column. All important preprocessor instructions are listed below:
instruction | describe |
---|---|
#define | Define the macro |
#include | Contains a source code file |
#undef | Cancels defined macros |
#ifdef | Returns true if the macro is already defined |
#ifndef | Returns true if the macro is not defined |
#if | If the given condition is true, the following code is compiled |
#else #if | Alternatives to |
#elif | If the previous #if given condition is not true and the current condition is true, compile the following code |
#endif | End a #if… #else conditional compiler block |
#error | When a standard error is encountered, an error message is printed |
#pragma | Use standardized methods to issue special commands to the compiler |
Macro definition, macro replacement
1. Define the identity
(1) For example, to determine whether a certain syntax, platform, etc., is supported by judging whether some identifiers are defined:
// indicates support for C++ syntax
#ifdef __cplusplus
#endif // __cplusplus
Copy the code
// Indicates support for Android, Windows, Apple, etc
#ifdef ANDROID
#endif // ANDROID
Copy the code
(2) Prevent repeated introduction of header files:
For example, we have three files a.h, b.h, and test.cpp, as follows:
This is the a.h:
#include "b.h"
void a(a);
Copy the code
This is the b.h:
#include "a.h"
void b(a);
Copy the code
Finally, test. CPP references a.H.
#include "a.h"
Copy the code
Thus, when Test contains a, A contains B, and B contains A, creating a loop of inclusion. Similar to the SQL circular reference in Hibernate. The following error will be reported:
Fatal Error C1014: Contains too many files: depth =1024
Copy the code
This problem can be solved by macro definition judgment: A.H.
#ifndef AH // if AH is not specified, only the following statement will be executed. If AH is defined, the following statement will not be executed
#define AH
#include "B.h"
void printfA(a);
#endif
Copy the code
B.h
#ifndef BH
#define BH
#include "A.h"
void printfB(a);
#endif
Copy the code
In addition, the new version solves this problem with the #pragma once statement.
// The header is included only once, and the compiler handles loop inclusion automatically
#pragma once
#include "B.h"
Copy the code
2. Define constants (easy to modify and read)
#define MAX 100
void main(a){
int i = 100;
if (i == MAX){
printf("Ha ha");
}
getchar(a); }Copy the code
3. Define “macro functions”.
It’s essentially a substitution process.
Example:
#include <stdio.h>
#include <stdlib.h>
#define GET_MIN(A,B) A < B ? A : B
int main(a){
int a = 100;
int b = 200;
int c = GET_MIN(100.200);
printf("Minimum value: %d\n", c);
getchar(a);return 0;
}
Copy the code
Result output:
Minimum value: 100Copy the code
An example of a simplified Android LOG:
C language macro function print statement simple use:
#define LOG(FORMAT,...) printf(FORMAT,__VA_ARGS__);
Copy the code
. Three dots indicate that the variable argument has a LOG level corresponding to __VA_ARGS__, thus further upgrading:
#define LOG_I(FORMAT,...) printf("INFO:"); printf(##FORMAT,__VA_ARGS__);
#define LOG_E(FORMAT,...) printf("ERROR:"); printf(##FORMAT,__VA_ARGS__);
Copy the code
To further simplify duplicate code, repeat LEVEL log LEVEL:
#defineLOG(LEVEL,FORMAT,...) printf(LEVEL); printf(##FORMAT,__VA_ARGS__);
#defineLOG_I(FORMAT,...) LOG("INFO:",FORMAT,__VA_ARGS__);
#defineLOG_E(FORMAT,...) LOG("ERROR:",FORMAT,__VA_ARGS__);
#defineLOG_D(FORMAT,...) LOG("DEBUG:",FORMAT,__VA_ARGS__);
Copy the code
When Android JNI was being developed, we printed a log sentence using the __android_log_print function
__android_log_print(ANDROID_LOG_INFO, "FFmpeg"."%s"."fix");
Copy the code
In the same way, practical use simplifies code by defining macros:
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"FFmpeg",FORMAT,##__VA_ARGS__);
LOGI("%s"."fix");
Copy the code
Predefined macro
ANSI C defines many macros. You can use these macros in programming, but you cannot directly modify the predefined macros.
The macro | describe |
---|---|
__ DAT__ | The current date, a character constant in the format “MMM DD YYYY”. |
__ TIME__ | The current time, a character constant in “HH:MM:SS” format. |
__ FILE__ | This will contain the current filename, a string constant. |
__ LINE__ | This will contain the current line number, a decimal constant. |
__ STDC__ | Is defined as 1 when the compiler compiles to ANSI standards. |
Let’s try the following example:
#include <stdio.h>
main()
{
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}
Copy the code
When the above code (in file test.c) is compiled and executed, it produces the following results:
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
Copy the code
Preprocessor operator
The C preprocessor provides the following operators to help you create macros: macro continuation operator (\) A macro is usually written on a single line. But if the macro is too long to fit on a single line, the macro continuation operator (\) is used. Such as:
#define message_for(a, b) \
printf(#a " and " #b ": We love you! \n")
Copy the code
String constant quantization operator#
In macro definitions, the string constant quantization operator is used when a macro parameter needs to be converted to a string constant#
. The operator used in macros has a specific argument or argument list. Such as:
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you! \n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}
Copy the code
When the above code is compiled and executed, it produces the following results:
Carole and Debra: We love you!
Copy the code
Tag paste operator# #
The mark-paste operator within the macro definition# #
Two parameters are merged. It allows two independent tags to be combined into a single tag in a macro definition.
Example 1
#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
Copy the code
Result output:
token34 = 40
Copy the code
Because this example produces the following actual output from the compiler:
printf ("token34 = %d", token34);
Copy the code
This example demonstrates that token##n will be connected to token34, where we use the string constant quantization operator # and the tag paste operator ##.
Example 2
#include <stdio.h>
// Method names are long (method names are regular)
int com_haocai_ndk_get_min(int a,int b){
return a < b ? a : b;
}
int com_haocai_ndk_get_max(int a,int b){
return a > b ? a : b;
}
// Syntax specification
/ / # define labeled NAME (the method NAME, A, B) com_tz_ndk_get_ # # NAME (A, B)
#define call(NAME,A,B) com_haocai_ndk_get_##NAME(A,B)
int main(a){
int c = call(min,100.200);
printf("Minimum value :%d\n",c);
int d = call(max,100.200);
printf("Max :%d\n",d);
getchar(a);return 0;
}
Copy the code
Result output:
Minimum value :100 Maximum value :200Copy the code
The defined () operator
The preprocessor defined operator is used in constant expressions to determine whether an identifier has already been defined using #define. The value is true (non-zero) if the specified identifier is defined. If the specified identifier is not defined, the value is false (zero). The following example demonstrates the use of the defined() operator:
#include <stdio.h>
#if! defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void)
{
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
Copy the code
When the above code is compiled and executed, it produces the following results:
Here is the message: You wish!
Copy the code
Parameterized macros
A powerful feature of CPP is the ability to simulate functions using parameterized macros. For example, the following code calculates the square of a number:
int square(int x) {
return x * x;
}
Copy the code
We can rewrite the above code using macros as follows:
#define square(x) ((x) * (x))
Copy the code
Before using a macro with parameters, you must use the #define directive. The argument list is enclosed in parentheses and must be immediately followed by the macro name. No Spaces are allowed between the macro name and the opening parenthesis. Such as:
#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
printf("Max between 20 and 10 is %d\n".MAX(10.20));
return 0;
}.
Copy the code
When the above code is compiled and executed, it produces the following results:
Max between 20 and 10 is 20
Copy the code