今天写个第二遍吧,这篇有点×疼,大家见谅。
先看代码:
1 2 3 4 5 6 7 | #include <stdio.h> int main() { printf("%s", "What's this??!\n"); return 0; } |
1 2 3 4 5 6 7 | int main() { int a = 0; //What's a's value??????????????/ a++; return 0; } |
想想上面两段代码吧……
好了,答案在这里,在符合 C99 的编译器里,第一段输出 What's this|,第二段 a 的值还是零。为什么这样呢,因为 C99 增加了一个叫 trigraph 的特性,也就是三元组。由于某些键盘上无法输入某些字符,所以就定义三个字符来替代那一个字符,比如 ??! 会转换成 |,??/ 会转换成 \,也就是说 a++ 也成了注释的一部分,(三元组都是两个问号开头的),而且无论是在字符串中还是注释中都会被替换(在预处理器中进行替换,不论在代码的哪里出现都会被替换)。这样就能解释上面两段代码的输出了。想要避免这个问题可以将 ? 进行转义(写成 \?),或者把字符串拆开(写成 "?""?""!")。
还有一种叫做 digraph,二元组,也就是用两个字符来表示一个字符。与三元组不同的是,二元组被当成一个独立的 token 来解释,在预处理器进行词法分析的时候被替换,也就是说,在字符串中和包括在其他 token 中的二元组不会被替换掉,这样就不会造成像三元组那样诡异的问题了。
为啥说这篇×疼的,是因为 GCC 默认不开启三元组的支持(M$ 的编译器不清楚)……想要开启需要在编译时指定 -std 或者 -trigraphs,没有这两个编译选项的时候出现三元组不会发生替换,编译时会有警告。
我觉得这东西平时没啥用,不要误用了就好。
References:
- http://en.wikipedia.org/wiki/Digraphs_and_trigraphs
- http://gcc.gnu.org/onlinedocs/cpp/Initial-processing.html
- http://gcc.gnu.org/onlinedocs/cpp/Tokenization.html
- http://stackoverflow.com/questions/1995113/strangest-language-feature/1995134#1995134

支持一下~
X痛了吧.一个月总有几天不舒服吧.
这个比较杯具!