为什么三字母在现代C ++编译器中会产生错误?

问题描述 投票:8回答:4

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

#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编译器中编译。你可以招募一些能够处理和处理三字符而没有任何错误或警告的编译器吗?

c++ c gcc compiler-errors
4个回答
10
投票

Trigraphs由1989 ANSI C标准引入,并保留在所有后来的C标准中。它们也出现在1998年出版的第一个ISO C ++标准中,以及所有后来的C ++标准中,包括C ++ 14。 (Trigraphs在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;
}

打印oops,然后你的编译器不符合。

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

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

Trigraphs很少使用。绝大多数开发系统直接支持三角形替代的所有角色:#[\]^{|}~

事实上,可能会比使用正确使用三角戟更频繁地使用三角戟:

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

关于可能改变程序含义的三字母的警告(相对于语言没有三字母时的意义)是ISO标准允许的,并且恕我直言非常合理。大多数编译器可能有选项来关闭此类警告。

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


5
投票

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

gcc -trigraphs ...

GCC 4.7.1手册说:

-trigraphs

支持ISO C三字符。 -ansi选项(以及严格的ISO C一致性的-std选项)意味着-trigraphs

它还说:

-Wtrigraphs

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


2
投票

他们可能是turned off by default

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

GCC might be one of the latter。虽然它应该默认为ignore with warning,但在这种情况下忽略可能会导致编译错误


1
投票

Trigraph在编译的早期阶段进行转换,甚至可以用字符串文字替换。这使得由三字母翻译引起的错误很难检测到(如果您考虑使用日志进行调试并且在源中找到输出,则会出现最糟糕的情况)。

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

© www.soinside.com 2019 - 2024. All rights reserved.