即使在GCC编译器中,如果不显式指定三字母属性,三字母也不会被编译。
#include<stdio.h> int main() { int a=4; if((a==4) ??! (a==5)) printf("\nHello world!"); return 0; }
这个保存为try.c的程序只有在我们指定gcc -Wall -trigraphs try.c时才能在GCC编译器中编译,而且它仍然显示警告。你能找到一些编译器来处理三字母而不显示任何错误或警告吗?
gcc -Wall -trigraphs try.c
7bsow1i61#
三字母是由1989年ANSI C标准引入的,并且保留在所有后来的C标准中(到目前为止;它们也出现在1998年发布的第一个ISO C标准中,以及所有后来的C标准中,直到C14。(三合字母在C17中被删除。感谢Jonathan Leffler和dyp追踪细节。)引用C17标准的草案:对原始特征的影响:使用三字母的有效C 2014代码可能是无效的,或者在本国际标准中可能具有不同的语义。如果三字母出现在原始字符串文字之外,作为实现定义的从物理源文件字符到基本源字符集的Map的一部分,实现可以选择转换C++ 2014中指定的三字母。在C++17之前的语言中,它们不是可选的特性;所有符合的编译器 * 必须 * 支持它们,并按照各自语言标准的规定解释它们。例如,如果此程序:
#include <stdio.h> int main(void) { if ('|' == '??!') { puts("ok"); } else { puts("oops"); } return 0; }
打印oops,则您的编译器不符合。但是很多,也许是大多数,C编译器在默认情况下并不是完全符合标准的。只要编译器能够以某种方式符合标准,就足以满足标准的要求。(gcc需要-pedantic和-std=...来做到这一点。)但是,即使编译器完全符合标准,标准中也没有禁止编译器发出任何警告。符合标准的C编译器必须诊断任何违反语法规则或约束的情况,但它可以发出任意多的附加警告--而且它不需要区分所需的诊断和其他警告。三字母很少被使用,绝大多数的开发系统都直接支持三字母所替代的所有字符:第一个月第三个月事实上,三合字的使用很可能是“意外”的,而不是正确的:
oops
-pedantic
-std=...
fprintf(stderr, "What just happened here??!\n");
关于可能改变程序含义的三合字的警告(相对于语言没有三合字时的含义)是ISO标准允许的,恕我直言,这是完全合理的。大多数编译器可能都有关闭这种警告的选项。相反,对于一个 * 不 * 实现三字母的C17编译器,警告那些在C14或更早版本中被视为三字母的序列是合理的,并且/或者提供一个支持三字母的选项。同样,一个禁用这样的警告的选项也是一件好事。
xbp102n02#
GCC不支持三字母。您必须显式地启用它们:
gcc -trigraphs ...
GCC 4.7.1手册中指出:-trigraphs支持ISO C三合字。-ansi选项(以及用于严格ISO C一致性的-std选项)隐含-trigraphs。上面还说:-Wtrigraphs如果遇到任何可能改变程序含义的三合字,则发出警告(注解中的三合字不会发出警告)。此警告由-Wall启用。
-trigraphs
-ansi
-std
-Wtrigraphs
-Wall
mbzjlibv3#
默认情况下,它们可能处于关闭状态。某些编译器支持关闭三字母识别得选项,或者在默认情况下禁用三字母识别并需要一个选项来打开它们GCC might be one of the latter.ignore with warning虽然它在默认情况下应该是ignore with warning,但在这种情况下忽略可能会导致编译错误
wxclj1h54#
三字母在编译的早期就被转换了,甚至可以被替换成字符串文字。这使得三字母翻译产生的错误很难被检测到(如果你考虑使用日志调试,并且在源代码中找到输出,情况会更糟)。你看到的警告将帮助你快速找到可能的罪魁祸首,追踪bug的来源。基本上,它是在警告你,有些东西可能并不像你想象的那样。
4条答案
按热度按时间7bsow1i61#
三字母是由1989年ANSI C标准引入的,并且保留在所有后来的C标准中(到目前为止;它们也出现在1998年发布的第一个ISO C标准中,以及所有后来的C标准中,直到C14。(三合字母在C17中被删除。感谢Jonathan Leffler和dyp追踪细节。)
引用C17标准的草案:
对原始特征的影响:使用三字母的有效C 2014代码可能是无效的,或者在本国际标准中可能具有不同的语义。如果三字母出现在原始字符串文字之外,作为实现定义的从物理源文件字符到基本源字符集的Map的一部分,实现可以选择转换C++ 2014中指定的三字母。
在C++17之前的语言中,它们不是可选的特性;所有符合的编译器 * 必须 * 支持它们,并按照各自语言标准的规定解释它们。
例如,如果此程序:
打印
oops
,则您的编译器不符合。但是很多,也许是大多数,C编译器在默认情况下并不是完全符合标准的。只要编译器能够以某种方式符合标准,就足以满足标准的要求。(gcc需要
-pedantic
和-std=...
来做到这一点。)但是,即使编译器完全符合标准,标准中也没有禁止编译器发出任何警告。符合标准的C编译器必须诊断任何违反语法规则或约束的情况,但它可以发出任意多的附加警告--而且它不需要区分所需的诊断和其他警告。
三字母很少被使用,绝大多数的开发系统都直接支持三字母所替代的所有字符:第一个月第三个月
事实上,三合字的使用很可能是“意外”的,而不是正确的:
关于可能改变程序含义的三合字的警告(相对于语言没有三合字时的含义)是ISO标准允许的,恕我直言,这是完全合理的。大多数编译器可能都有关闭这种警告的选项。
相反,对于一个 * 不 * 实现三字母的C17编译器,警告那些在C14或更早版本中被视为三字母的序列是合理的,并且/或者提供一个支持三字母的选项。同样,一个禁用这样的警告的选项也是一件好事。
xbp102n02#
GCC不支持三字母。您必须显式地启用它们:
GCC 4.7.1手册中指出:
-trigraphs
支持ISO C三合字。
-ansi
选项(以及用于严格ISO C一致性的-std
选项)隐含-trigraphs
。上面还说:
-Wtrigraphs
如果遇到任何可能改变程序含义的三合字,则发出警告(注解中的三合字不会发出警告)。此警告由
-Wall
启用。mbzjlibv3#
默认情况下,它们可能处于关闭状态。
某些编译器支持关闭三字母识别得选项,或者在默认情况下禁用三字母识别并需要一个选项来打开它们
GCC might be one of the latter.ignore with warning虽然它在默认情况下应该是ignore with warning,但在这种情况下忽略可能会导致编译错误
wxclj1h54#
三字母在编译的早期就被转换了,甚至可以被替换成字符串文字。这使得三字母翻译产生的错误很难被检测到(如果你考虑使用日志调试,并且在源代码中找到输出,情况会更糟)。
你看到的警告将帮助你快速找到可能的罪魁祸首,追踪bug的来源。基本上,它是在警告你,有些东西可能并不像你想象的那样。