如果我將一個宏定義爲#define LOGIC_ONE 1
並且想在case語句中使用LOGIC_ONE
,那麼究竟是什麼類型的LOGIC_ONE
?宏是什麼類型的考慮?
是它識別爲int
,因爲我定義它的值1?
如果我將一個宏定義爲#define LOGIC_ONE 1
並且想在case語句中使用LOGIC_ONE
,那麼究竟是什麼類型的LOGIC_ONE
?宏是什麼類型的考慮?
是它識別爲int
,因爲我定義它的值1?
C++宏是簡單的文本替換。
在編譯器啓動時,預編譯器已將LOGIC_ONE
替換爲1
。它就好像你會立刻寫上1
一樣。 (在這種情況下,是文字的一個int ...)
編輯在意見討論:
如果您(或其他人訪問您的代碼)改變你#define LOGIC_ONE 1
到#define LOGIC_ONE "1"
它會改變它在你的程序中的行爲,併成爲一個const char[]
文字。
編輯:
由於這個帖子得到了更多的關注比我預期,我想我的引用添加到C++ 14 Standard對於那些好奇:
2.2階段的翻譯 [lex.phases]
(...)
4.執行預處理指令,展開宏調用,並執行 _Pragma一元運算符表達式。 (...)然後刪除所有預處理指令。
(...)
7.分隔標記的空白字符不再重要。每個預處理令牌都被轉換爲令牌。 (2.6)。所產生的令牌在語法和語義上被分析並翻譯爲翻譯單元。
如前所述,宏在階段4中被替換,之後不再存在。 「語法和語義」分析發生在階段7,代碼被編譯(「翻譯」)。
整數常量在
2.13.2整數常量指定 [lex.icon]
(...)
一個整數文字是具有無期或指數的數字序列部分,可選分隔單引號,在確定其值時會被忽略。整數文字可能有一個前綴,用於指定其基數和一個指定其類型的後綴。
(...)表5 -
Suffix | Decimal literal | Binary, octal, or hexadecimal literal ----------------------------------------------------------------------------- none | int | int | long int | unsigned int | long long int | long int | | unsigned long int | | long long int | | unsigned long long int ----------------------------------------------------------------------------- u or U | unsigned int | unsigned int | unsigned long int | unsigned long int | unsigned long long int | unsigned long long int ----------------------------------------------------------------------------- l or L | long int | long int | long long int | unsigned long int | | long long int | | unsigned long long int ----------------------------------------------------------------------------- Both u or U | unsigned long int | unsigned long int and l or L | unsigned long long int | unsigned long long int ----------------------------------------------------------------------------- ll or LL | long long int | long long int | unsigned long long int ----------------------------------------------------------------------------- Both u or U |unsigned long long int | unsigned long long int and ll or LL | |
字符串文本在
2.13.5字符串文字 [lex.string]指定的整數文字的類型
(...)
1字符串文字是由雙引號括起來的一系列字符(如2.13.3中定義的),可選地以R,u8,u8R,u,uR,U,UR,L,rLR作爲前綴,如「 ...「,R」(...)「,u8」...「,u8R」**(...)**「,u」...「,uR」*〜(...) *「,U」...「,UR」zzz(...)zzz「,L」...「或LR」(...)「。
(...)
6翻譯階段6之後,不以編碼前綴開始的字符串文字是普通的字符串文字,並且使用給定的字符進行初始化。
7以u8開頭的字符串文字,例如u8「asdf」,是一個UTF-8字符串文字。
8普通字符串文字和UTF-8字符串文字也被稱爲窄字符串文字。窄字符串文字具有類型「nconst char
」的數組,其中n是如下定義的字符串的大小,並具有 靜態存儲持續時間(3.7)。
I.e.我可以把'LOGIC_ONE'看作是一個'int'嗎? – Noobgineer
@Noobgineer當前值是,但是如果有人將它改爲'「1」' –
你可以用任何你可以對待'1'的方式來對待它 - 所以是的,它是一個整型文字。 – Anedar
LOGIC_ONE在任何地方都會被替換爲1。就編譯器而言,LOGIC_ONE不存在,它只是看到1.所以你的問題是'是1是一個int?'。答案就是 - >這取決於你在哪裏鍵入1
好的。我不知道編譯器是尋找'1'還是'LOGIC_ONE'。謝謝你的澄清! – Noobgineer
宏是一個文本替換。 1
類型爲constexpr int
。
預處理器定義沒有類型 - 它們基本上只是「粘貼」到它們出現的代碼中。例如,如果您在聲明中使用它,
int foo = LOGIC_ONE;
然後它會被解釋爲整數。 (編譯器,在預處理器之後運行,只能看到代碼爲int foo = 1;
)您甚至可以在一個糟糕的語句中使用它,例如;
int foo##LOGIC_ONE;
然後,您將創建一個變量foo1
。育!
舉一個宏定義的替代例子;
#define LOGIC_ONE hello
int LOGIC_ONE = 5;
printf("%d\n", hello);
這是完全有效的,並宣佈名爲hello int,但表明,沒有「型」的定義 - hello
只是被取代的地方LOGIC_ONE
在代碼中遇到。
避免使用預處理器宏,除非絕對必要。專業編碼標準通常禁止或嚴格限制預處理器的使用。通常總是有比使用宏更好的方法來做事。例如,考慮這些替代方案;
static const int LOGIC_ONE = 1;
enum { LOGIC_ONE = 1 };
預處理器是學習者在一個真正的混亂得到C.
感謝您的詳細解釋。這些宏是作爲API的一部分提供的,我必須使用並且不允許修改,但是我會在避免預處理器宏的情況下爲您的未來努力提供建議! – Noobgineer
我認爲令牌粘貼只適用於宏參數,並且一般不應用於宏? – supercat
針對宏的非常有限使用的建議在C++中是10倍(這個問題被標記)。幾乎可以肯定,無論您使用宏都可以實現哪種安全方式,它都是更好的類型安全方法。文件包含,包括警衛和條件編譯是預處理的剩餘主要停留。 – Persixty
要查看預處理器不,傳給'-E'到編譯器的快捷方式。 (msvc,gcc,clang都接受'-E') – Ben