C++ "#"的作用和使用方法
本系列文章由 @yhl_leo 出品,轉載請註明出處。
文章鏈接: http://blog.csdn.net/yhl_leo/article/details/48879093
1 #
和##
的作用和使用方法
C/C++ 的宏中,#
的功能是將其後面的宏參數進行字符串化操作。簡單說就是在對它所引用的宏變量通過替換後在其左右各加上一個雙引號。##
連接符號由兩個井號組成,其功能是在帶參數的宏定義中將兩個子串聯接起來,從而形成一個新的子串。
但它不能夠是第一個或者最後一個子串。
#include <iostream>
using namespace std;
#define WARN_IF(EXP) if(EXP) cerr << #EXP << endl;
#define paster( n ) cout << "token" << #n << " = " << n << endl;
#define _CONS(a, b) int(a##+##b)
#define _STRI(s) #s
void main()
{
int div = 0;
WARN_IF(div == 0); // prints : div == 0
paster(9); // prints : token9 = 9
cout << _CONS(1 , 2) << endl; // prints : 3
cout << _STRI(INT_MAX) << endl; // prints : INT_MAX
}
凡是宏定義裏實用#
或##
的地方宏參數是不會再展開,比如_STRI(INT_MAX)
中的INT_MAX
就不會被展開為2147483647。
假設想要使當中的宏參數展開,則須要多加一層中間轉換宏:
#define STRI(s) _STRI(s)
cout << STRI(INT_MAX) << endl; // prints : 2147483647
加這層宏的用意是把全部宏的參數在這層裏全部展開。那麽在轉換宏裏的宏就能得到對應的宏參數。
接下來,我們來了解通過預處理指令創建條件編譯參數控制代碼編譯的一些使用方法。
2 #include
的使用方法
包括頭文件的操作,通常有兩種格式:
#include <header-file>
#include "header-file"
<>
和""
表示編譯器在搜索頭文件時的順序不同:
<>
表示從系統文件夾下開始搜索,然後再搜索PATH環境變量所列出的文件夾,不搜索當前文件夾""
是表示從當前文件夾開始搜索,然後是系統文件夾和PATH環境變量所列出的文件夾。
所以,系統頭文件一般用<>
,用戶自定義的則能夠使用""
,加快搜索速度。
除此外,寫代碼多了就會發現,有些頭文件之間的相互包括是有隱藏依賴關系的。一定要加以註意。Google C++ Style Guide中也強調使用標準的頭文件包括順序可增強可讀性, 避免隱藏依賴:
1 相關文件(優先位置,如
dir2/foo2.h
)
2 C系統文件
3 C++ 系統文件
4 其它庫的.h
文件
5 本項目內.h
文件
3 #if
,#elif
,#else
,#endif
使用方法
// structure 1
#if constant_expression
#else
#endif
// structure 2
#if constant_expression
#elif constant_expression
#endif
這裏的結構跟常見的if...else
和if...else if...else
語句相似,當#if
後的條件為非零(true)時,編譯#if
和#else
或#elif
之間的代碼。否則編譯#else
和#endif
之間的代碼(或者推斷#elif
後的條件是否非零(true),決定是否編譯#elif
和#endif
之間的代碼)。
#if 1
cout << "Hello world!" << endl;
#else
cout << "Nice to meet you!" << endl;
#endif
// prints : Hello world!
#if 1
cout << "Hello world!" << endl;
#elif 1
cout << "Nice to meet you!" << endl;
#endif
// prints: Hello world!
// Nice to meet you!
4 #define
,#undef
,#ifdef
,#ifndef
使用方法
#define
是大家都常見的宏定義方法。使用方法結構為:
// #define identifier replacement-code
#define PI 3.1415926
#define ADD(x,y) (x + y)
#undef
顧名思義。就是從該處取消前面已經定義的宏,假設標識符當前沒有被定義稱為一個宏名稱,就會忽略該指令:
// #undef identifier
#undef PI
#ifdef
和#ifndef
含義相反,前者含義為假設定義了該宏。則編譯對應代碼;後者則為假設未定義該宏。則編譯對應代碼。通用結構為:
/*
* #ifdef identifier
* #else or #elif
* #endif
**/
#define DEBUG
#ifdef DEBUG
cout << "This is a debug message." << endl;
#endif
// prints : This is a debug message.
/*
* #ifndef identifier
* #else or #elif
* #endif
**/
#ifndef DEBUG
cout << "This is a debug message." << endl;
#endif
// prints nothing
在編程時,為了避免頭文件重定義,常常使用的就是#define
配合條件編譯解決:
#ifndef MY_HEADER_FILE_H
#define MY_HEADER_FILE_H
// ...
class MyHeaderFile
{
// ....
};
#endif // MY_HEADER_FILE_H
除此以外,還有#pragma once
的使用方法,僅僅要在頭文件的最開始增加這條指令就能夠保證頭文件被編譯一次。
(在全部的預處理指令中,#pragma
指令可能是最復雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完畢一些特定的動作,本文不多講述。)
5 #line
使用方法
#line
命令是用於更改__LINE__
和 __FILE__
變量的值。
__FILE__
和__LINE__
描寫敘述被讀取的當前文件和所在行數。
// #line line-number filename
int main()
{
#line 10 "main.cpp"
cout << __FILE__ << " " << __LINE__ << endl;
}
// prints : main.cpp 10
6 #error
使用方法
#error
會直接導致程序停止編譯並輸出指定的錯誤信息:
// #error message
#ifndef VERSION
#error Version number not specified.
#endif
// The compiler will halt compiling and return with the specified error message:
// fatal error C1189: #error : Version number not specified.
C++ "#"的作用和使用方法