#define
DESCRIPTION: 定義一個宏
NOTE:
1 所有用於表達式求值的宏定義都應該對參數加上括號,避免在使用宏時,由於參數中操作符或鄰近的操作符之間不可預料的相互作用
2 宏與類型無關
USAGE1: #define name [stuff]
EXPLANATION: 當符號出現在這條指令後面時, 預處理就會把它替換成stuff
COMMAND: gcc -E main.c -o main.i
EXAMPLES:
#define reg register
#define do_forever for(;;)
#define CASE break;case
USAGE2: #define name(parameter-list) [stuff]
ATTENTION: parameter-list是一個由都好分隔的符號列表,它們可能出現在stuff中。
參數列表的左括號必須與name緊鄰,如果兩者之間有空白存在,參數列表就會被解釋爲stuff的一部分;
將宏參數插入到字符串常量中
SKILL1: 鄰近字符串自動鏈接的特性
#define PRINT(FORMAT, VALUE) \
printf("The value is " FORMAT "\n", VALUE)
PRINT("%d", 5)預處理後的結果爲: printf("The value is " "%d" "\n", 5) 等價於 printf("The value is %d \n", 5)
SKILL2: 使用預處理器把一個宏參數轉換爲一個字符串
#define PRINT(FORMAT, VALUE) \
printf("The value of " #VALUE \
" is " FORMAT "\n", VALUE)
PRINT("%d", x + 3) 預處理後的結果爲: printf("The value of " "x + 3" " is " "%d" "\n", x + 3) 等價於 printf("The value of x + 3 is %d\n", x + 3)
SKILL3:##將它兩邊的符號連接成一個符號, ##左右兩邊有無空格效果一樣
#define ADD_TO_SUM( sum_number, value) \
sum ## sum_number += value
ADD_TO_SUM(5, 5)預處理後的結果爲: sum5 += 5
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#undef
DESCRIPTION: 移除一個宏定義
USAGE: #undef name
命令行定義:
gcc -DNAME -E main.c -o main.i 定義一個宏NAME 等同於 #define NAME
gcc -DAGE=25 -E main.c -o main.i 定義一個宏AGE 25 等同於 #define AGE 25
gcc -DNAME="\"John\"" -E main.c -o main.i 定義一個宏NAME "John" 等同於 #define NAME "John"
gcc -DNAME -UNAME -E main.c -o main.i 相當於未定義宏 等同於 #define NAME #undef NAME
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if constant-expression
statements
#endif
DESCRIPTION: 條件編譯
EXPLANATION: constant-expression 常量表達式 -> 字面量或者由#define定義的符號
#if constant-expression
statements
#elif constant-expression
statements
#else
statements
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
DESCRIPTION: 判斷是否定義
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if defined( OS_UNIX )
#ifdef OPTION1
unix_version_of_option1();
#endif
#ifdef OPTION2
unix_version_of_option2();
#endif
#elif defined( OS_MSDOS )
#ifdef OPTION2
msdos_version_of_option2();
#endif
#endif
DESCRIPTION: 嵌套指令
#ifdef OPTION1
lengthy code for option1;
#else
lengthy code for alternative;
#endif /*OPTION1*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include
DESCRIPTION: 文件包含
USAGE:#include <filename>
#include "filename"
#include "/usr/lib/filename"
EXPLANATION: <filename> 和 "filename" 的區別: 前者在編譯器指定的位置查找函數庫頭文件,
後者先在當前目錄下查找指定文件,如果未找到的情況下再去編譯器指定的位置查找文件
"usr/lib/filename" 使用絕對路徑指定文件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifndef _HEADERNAME_H
#define _HEADERNAME_H 1
#endif
DESCRIPTION: 防止文件出現多次包含的情況發生
EXAMPLES:
main.h
#ifndef _MAIN_H
#define _MAIN_H 1
...
#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#error
DESCRIPTION: 生成錯誤信息
EXAMPLES:
#if defined( OPTION_A )
stuff needed option A
#elif defined( OPTION_B )
stuff needed option B
#elif defined( OPTION_C )
stuff needed option C
#else
#error No option selected
#endif /* 如果未定義OPTION_A OPTION_B OPTION_C 則預處理報錯 No option selected */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#line
USAGE: #line number [string]
DESCRIPTION: 修改__LINE__符號的值, 加上可選部分將修改__FILE__的值
EXPLANATION: number 爲下一行輸入的行號 可選字符串[string] 將修改__FILE__的值
EXAMPLES:
main.c
1 #include <stdio.h>
2
3 #line 5 "TEST"
4
5 void main() {
6 printf("%d\n", __LINE__);
7 printf("%s\n", __FILE__);
8 }
#line 5 "TEST"
此時第四行的行號修改爲第5行,所以此時__LINE__的值爲7
此時__FILE__的值爲"TEST"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#progma
DESCRIPTION: 用於支持因編譯器而異的特性, 不可移植