8

带有使用 Turbo C++ 编译的三元组的程序的屏幕截图

即使在 GCC 编译器中,如果没有明确指定 trigraph 属性,也不会编译 trigraph。

#include<stdio.h>

int main()
 {
 int a=4;
 if((a==4) ??! (a==5))
   printf("\nHello world!");
 return 0;
 }

这个保存为 try.c 的程序只有在我们指定时才会在 GCC 编译器中编译gcc -Wall -trigraphs try.c,它仍然显示警告。你能招募一些编译器来处理和处理三元组而不会出现任何错误或警告吗?

4

4 回答 4

10

三元组由 1989 年的 ANSI C 标准引入,并保留在所有后来的 C 标准中。它们还出现在 1998 年发布的第一个 ISO C++ 标准中,以及后来的所有 C++ 标准中,直到并包括 C++14。(三合符在 C++17 中被删除。感谢 Jonathan Leffler 和 dyp 追踪细节。)

引用 C++17 标准的草案:

对原始特征的影响:使用三元组的有效 C++ 2014 代码在本国际标准中可能无效或可能具有不同的语义。如果三元组出现在原始字符串文字之外,实现可以选择转换 C++ 2014 中指定的三元组,作为实现定义的从物理源文件字符到基本源字符集的映射的一部分。

它们不是任何一种语言的可选功能(C++17 之前);所有符合标准的编译器都必须支持它们并按照各自语言标准的规定解释它们。

例如,如果这个程序:

#include <stdio.h>
int main(void) {
    if ('|' == '??!') {
        puts("ok");
    }
    else {
        puts("oops");
    }
    return 0;
}

prints oops,那么您的编译器不合格。

但是许多,也许是大多数,C 编译器默认情况下并不完全符合。只要可以使编译器以某种方式符合标准,就标准而言,这就足够了。(gcc 需要-pedantic-std=...这样做。)

但即使编译器完全符合标准,标准中也没有任何内容禁止编译器警告它喜欢的任何东西。符合标准的 C 编译器必须诊断出任何违反语法规则或约束的行为,但它可以发出任意数量的附加警告——它不需要区分所需的诊断和其他警告。

三元组很少使用。绝大多数开发系统直接支持三元组替代的所有字符:#, [, \, ], ^, {, |, }, ~.

事实上,三元组的意外使用可能比正确使用的频率更高:

fprintf(stderr, "What just happened here??!\n");

关于可能改变程序含义的三元组的警告(相对于如果语言没有三元组的含义)是 ISO 标准允许的,恕我直言,这是完全合理的。大多数编译器可能都有关闭此类警告的选项。

相反,对于实现三元组的 C++17 编译器,警告在 C++14 或更早版本中可能被视为三元组的序列和/或提供支持三元组的选项是合理的。同样,禁用此类警告的选项将是一件好事。

于 2012-12-02T08:33:45.153 回答
5

GCC 对三元组过敏。您必须明确启用它们:

gcc -trigraphs ...

GCC 4.7.1 手册说:

-trigraphs

支持 ISO C 三元组。该-ansi选项(以及-std严格符合 ISO C 的选项)意味着-trigraphs.

它还说:

-Wtrigraphs

如果遇到任何可能改变程序含义的三元组,则发出警告(注释中的三元组不会被警告)。此警告由 启用-Wall

于 2012-11-29T05:43:45.830 回答
2

它们可能默认关闭

“一些编译器支持关闭三字母识别的选项,或默认禁用三字母并需要一个选项来打开它们”

GCC 可能是后者之一。虽然默认情况下它应该忽略并发出警告,但在这种情况下,忽略可能会导致编译错误

于 2012-11-29T05:39:39.903 回答
1

三元组在编译的早期阶段就被转换,甚至可以用字符串文字替换。这使得三元组翻译产生的错误很难检测到(如果您考虑使用日志进行调试并且在源代码中找到输出,则情况会更糟)。

您看到的警告将帮助您快速发现可能的罪魁祸首以跟踪错误的来源。基本上它是在警告你,有些事情可能不像你想象的那样。

于 2012-11-29T05:59:38.317 回答