先用簡單的話講一下什麼是trigraph吧,這樣不會一上來就是沒人看得懂的話,trigraph是三字母詞,又叫三連字。
言歸正傳,總得來說,thrgraph是C/C++ 為了照顧老一輩的"無產階級革命家"而出現的,當時他們的條件極其艱苦,鍵盤上缺了很多鍵,無法輸入以下九個字符:
# \ ^ [ ] { } | ~
由此推才出現了 trigraph .
換句話說,就是把上面的每個字符用其他三個字符來代替,替換規則如下:
# ??=
\ ??/
^ ??'
[ ??(
] ??)
{ ??<
} ??>
| ??!
~ ??-
下面舉個例子來說明,下面是一個C++的簡單程序:
#include <iostream>
using namespace std;
int main() {
cout << "[]" << endl;
return 0;
}
在當時鍵盤沒有那九個符號的時候,那些程序員們就這麼寫:
??=include <iostream>
using namespace std;
int main() ??<
cout << "??(??)" << endl;
return 0;
??>
以上內容轉自百度上搜到的某個空間看到的,空間名叫"草"...
將 trigraph 替換成對應的字符發生在預處理之前,因此 trigraph 可以在源碼中的任何位置都可以用,包括字符串內,函數體開頭,預處理指令等。
有人說,如果那我就是用一個字符串常量,其中包含了 "??=" 怎麼辦?比如說就是要打印兩個問號接一個等號,怎麼辦?很簡單,把它拆開寫, 為了打印出 "??=",我們把它拆成 "??" "=" 即可,因為 C/C++ 在處理字符串字面值的時候,會把相鄰的多個字符串字面值合並成一個,而這個合並操作發生在 trigraph 替換之後,
下面的程序就可以正確的打印出兩個問號和一個等號:
#include <iostream>
using namespace std;
int main() {
cout << "??" "=" << endl;
}
實測中,
VC 8 不給任何提示將 trigraph 替換成對應字符,
GCC 4.0.3 則要求加上編譯參數 -trigraphs 才會做相應轉換。
雖然 GCC 的做法是不符合標准的,但是更加安全。
更詳細的情況可以參考標准 2.3。
以下是從c語言參考課程裡摘的一段話:
C源程序的源字符集被包含在7位ASCII字符集中,但不是ISO 646-1983Invariant Code Set的子集。三字母(trigraph)序列允許C程序僅使用ISO(國際標准組織) Invariant Code Set編寫。三字母是編譯器用對應的標點字符替換的三字符序列(以兩個問號開頭)。你可以在C源文件中使用三字母,該源文件的字符集不能包含某些標點字符的方便圖形表示。
一個三字母總是作為單個源字符處理,在第一次轉換階段中,在識別字符串文字和字符常量中的轉義字符之前進行三字母的轉換。僅識別表1.1中列出的9個三字母,所有其它字符序列不作轉換。
字符轉義序別\?防止類似三字母的字符序列被誤解釋(有關轉義序列的信息,參見本章後面的“轉義序列”)。例如,如果你試圖用以下printf語句打印字符串What??!:
printf(“What??!\n");
打印的字符串What|,因為??!是一個三字母,它被|字符所替換。正確打印這個字符串的語句如下:
printf(What?\?!\n");
在這個printf語句中,在第二個問號之前加上一個反斜槓轉義字符防止??!作為一個三字母的誤解釋。