[英]Implementation of string literal concatenation in C and C++
AFAIK,這個問題同樣適用於C和C ++
C標准中規定的“翻譯階段”的第6步(C99標准草案中的5.1.1.2)規定,必須將相鄰的字符串文字連接成單個文字。 即
printf("helloworld.c" ": %d: Hello "
"world\n", 10);
等同於(語法上):
printf("helloworld.c: %d: Hello world\n", 10);
但是,標准似乎沒有指定編譯器的哪個部分必須處理它 - 它應該是預處理器( cpp
)還是編譯器本身。 一些在線研究告訴我,這個函數通常應該由預處理器( 源#1 , 源#2 ,還有更多)執行,這是有道理的。
但是,在Linux中運行cpp
表明cpp
沒有這樣做:
eliben@eliben-desktop:~/test$ cat cpptest.c
int a = 5;
"string 1" "string 2"
"string 3"
eliben@eliben-desktop:~/test$ cpp cpptest.c
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "cpptest.c"
int a = 5;
"string 1" "string 2"
"string 3"
所以,我的問題是:在預處理器或編譯器本身中,應該在何處處理該語言的這一特性?
也許沒有一個好的答案。 基於經驗,已知編譯器和一般良好工程實踐的啟發式答案將不勝感激。
PS如果你想知道為什么我關心這個......我正在試圖弄清楚我的基於Python的C語法分析器是否應該處理字符串文字連接(目前它沒有這樣做),或者將它留給cpp
它假設在它之前運行。
該標准沒有指定預處理器與編譯器,它只是指定了您已經注意到的翻譯階段。 傳統上,階段1到階段4在預處理器中,編譯器中的階段5到階段7,以及階段8到鏈接器 - 但標准不需要這些階段。
除非指定預處理器來處理這個問題,否則可以安全地假設它是編譯器的工作。
編輯:
帖子開頭的“ Ie ”鏈接回答了以下問題:
相鄰的字符串文字在編譯時連接在一起; 這允許將長字符串拆分為多行,並且還允許在編譯時將C預處理器定義和宏生成的字符串文字附加到字符串...
在ANSI C標准中,第5.1.1.2節第(6)節中介紹了這一細節:
5.1.1.2翻譯階段
...
4.執行預處理指令並擴展宏調用。 ...
5.字符常量和字符串文字中的每個源字符集成員和轉義序列都將轉換為執行字符集的成員。
6.連接相鄰的字符串文字標記,並連接相鄰的寬字符串文字標記。
該標准沒有定義實現必須使用預處理器和編譯器本身。
第4步顯然是預處理者的責任。
步驟5要求“執行字符集”是已知的。 編譯器也需要此信息。 如果預處理器不包含平台依賴性,則將編譯器移植到新平台更容易,因此傾向於在編譯器中實現步驟5,從而實現步驟6。
字符串文字連接如何與轉義序列交互有一些棘手的規則。 假設你有
const char x1[] = "a\15" "4";
const char y1[] = "a\154";
const char x2[] = "a\r4";
const char y2[] = "al";
那么x1
和x2
必須根據strcmp
相等, y1
和y2
相同。 (這是Heath在引用轉換步驟時所遇到的 - 轉義轉換發生在字符串常量連接之前 。)還要求如果串聯組中的任何字符串常量具有L
或U
前綴,則會得到一個寬或者Unicode字符串。 把它們放在一起,作為“編譯器”的一部分,而不是“預處理器”,它可以更方便地完成這項工作。
我會在解析器的掃描令牌部分處理它,所以在編譯器中。 這似乎更合乎邏輯。 預處理器不知道語言的“結構”,事實上它通常會忽略它,因此宏可以生成不可編譯的代碼。 它只處理它有權處理的指令( # ...
),以及它們的“后果”(就像#define xh
,它會使預處理器發生很大的變化)。 x成h)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.