Author: Chen Xi
Date: 18:19:55
Environment: [Mac 10.7.1 lion intel I3 supports 64-bit gcc4.2.1 xcode4.2]
Reprinted please indicate the source
Q1: Macro is really strange. Why can't I replace the # include code with a macro?
#define INCLUDE_STDIO #include<stdio.h>INCLUDE_STDIOint main(){ return 0;}
Save as preprocess_header.c
A: if there is a problem with preprocessing, we can use-e to view the pre-processing result to analyze the problem.
Q2: As shown above, there seems to be no problem.
A: It seems that there is no problem. The problem is that the above result is the result after preprocessing. # Include still appears in the source code after compilation and preprocessing by the compiler. The Compiler does not recognize this, so an error is reported. In other words, when preprocessing is done, the compiler compiles the source code (but the compiler is often seen as a function that includes preprocessing ). the pre-processor can process # include, and the compiler cannot recognize # include.
Q3: When the include_stdio symbol is found to be # include <stdio. h>, why didn't I continue to pre-process the content of this header file?
A: This is because the C language standard stipulates that # define-defined symbols are re-preprocessed, but only # define symbols are allowed. # include is not processed when it is encountered.
Q4: Sometimes, you need to test data, write a lot of variables with the same name at the beginning, and finally assign values. What are the best methods?
A: Of course, this requires the # symbol. It can correctly generate the variable you need. The following code:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#define PRINT_D(longValue) printf(#longValue" is %ld\n", ((long)longValue));#define PRINT_STR(str) printf(#str" is %s\n", (str));#define ADD_TO_NUM(sum_name, sum_number, value) \(sum_name ## sum_number) += (value);int main(int argc, char **argv){ int sum1 = 10, sum2 = 20; int i = 10; ADD_TO_NUM(sum, 1, i); ADD_TO_NUM(sum, 2, i); PRINT_D(sum1) PRINT_D(sum2) return 0;}
Compile and run:
sum1 is 20sum2 is 30
Similarly, if you need to write operation functions of different types of data to the C language structure, such as stacks and queues, you can use the types as parameters to make macro definitions similar to those.
Q5: For do and while loops, I like to use the until mode. Is there any way?
A: The following code:
#define repeat do#define until(x) while(!(x))
Test code:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#define PRINT_D(longValue) printf(#longValue" is %ld\n", ((long)longValue));#define PRINT_STR(str) printf(#str" is %s\n", (str)); #define repeat do#define until(x) while(!(x))int main(int argc, char **argv){ int i = 1; repeat { PRINT_D(i) ++i; }until(i > 10); return 0;}
Running result:
i is 1i is 2i is 3i is 4i is 5i is 6i is 7i is 8i is 9i is 10
Q6: When writing code, I find that a keyword or code combination is always written. Is it a good choice to replace it with Macros?
A: As long as the risk is controllable, it is a good choice. For example, the register keyword is long and can be replaced by Reg. The Infinite Loop for (;) is also long and can be replaced by forever; you can use macro case to replace the break and case statements in the switch statement.
#define REG register#define FOREVER for(;;)#define CASE break; case
Test code:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#define PRINT_D(longValue) printf(#longValue" is %ld\n", ((long)longValue));#define PRINT_STR(str) printf(#str" is %s\n", (str)); #define REG register#define FOREVER for(;;)#define CASE break; caseint main(int argc, char **argv){ REG int i = 1; FOREVER PRINT_STR("hello") return 0;}
Here is an example of file read/write. I found that the fopen and fclose functions are always written many times. It is better to encapsulate them in a common file. using macros is a good choice:
#define FOPEN_COMMON(file_name) \FILE *fp = fopen((file_name), "r+"); \if(!fp) \{ \perror("fopen error"); \return -1; \}#define FCLOSE_COMMON \fclose(fp);
In short, it is a good choice to replace macros when there are many codes. However, you must be clear about the risks.
Q7: Since macros are the replacement of strings, can a basic type be defined as another basic type?
A: The C language standard does not stipulate that macro strings cannot be keywords, so the above situation is acceptable. However, this may disrupt the previous logic and can be tested on some occasions.
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#define PRINT_D(longValue) printf(#longValue" is %ld\n", ((long)longValue));#define PRINT_STR(str) printf(#str" is %s\n", (str));#define double intint main(int argc, char **argv){ double i = 1.5; PRINT_D(i) return 0;}
As you can see, the double string is defined as an int string above, and the Code for defining I in the main function is converted to int I = 1.5. The final output result is as follows:
i is 1
Q8: Sometimes, to facilitate the output of different types of variables, the following two macros are written:
#define PRINT(longValue) printf(#longValue" is %ld\n", ((long)longValue));#define PRINT(str) printf(#str" is %s\n", (str));
Why does it crash when print (1) is used again?
A: The macro does not support overloading like a function. It is a name and will not be considered different by the compiler because the macro parameters are different. Therefore, the above two print macros are actually considered as the same macro by the compiler, and there will be a redefinition warning:
warning: "PRINT" redefined
Therefore, print (1) actually uses the second macro. You can use the pre-processing command to obtain the pre-processing result. First, the source code is saved as preprocess_macro.c:
#include <stdio.h>#define PRINT(longValue) printf(#longValue"is %ld\n", (longValue));#define PRINT(str) printf(#str" is %s\n", (str));int main(){ PRINT(1) return 0;}
Use preprocessing to obtain the following results:
It can be seen that the macro print (STR) is used to replace it, resulting in a crash.
Q9: Sometimes I want to make some prompts based on the value of sizeof (INT). Why does the following code cause a compilation error?
#if sizeof(int) == 4#elif sizeof(int) == 8#warning "sizeof(int) == 8"#endif
A: This is because the C language standard stipulates that preprocessing cannot calculate the value of sizeof at all, and # The conditional expression after if must be an integer constant, so an error is prompted.
Q10: What if I want to control whether the int type is 4 or 8 bytes?
A: Actually, this is not something that programmers can control. It is determined by the platform. In Mac, gcc4.2.1, i386 mode Int Is 4 bytes, x86_64 mode Int Is also 4 bytes; however, the long type is 4 bytes in i386, and x86_64 mode is 8 bytes, after knowing the information above, it is best to use the type you need in the proper mode. The following is a test of the long type:
#include <stdio.h>int main(){ printf("%u\n", sizeof(long)); return 0;}
Save as preprocess_if.c.
Gcc-O preprocess_if preprocess_if.c-arch i386 is compiled and executed. The result is 4.
Gcc-O preprocess_if preprocess_if.c-arch x86_64 is compiled and executed. The result is 8.
Author: Chen Xi
Date: 18:19:55
Environment: [Mac 10.7.1 lion intel I3 supports 64-bit gcc4.2.1 xcode4.2]
Reprinted please indicate the source