简体   繁体   English

为什么GCC在使用三字符时会发出警告,但在使用有向图时则不会?

[英]Why does GCC emit a warning when using trigraphs, but not when using digraphs?

Code: 码:

#include <stdio.h>

int main(void)
{
  ??< puts("Hello Folks!"); ??>
}

The above program, when compiled with GCC 4.8.1 with -Wall and -std=c11 , gives the following warning: 上面的程序,当使用带-Wall-std=c11 GCC 4.8.1编译时,会发出以下警告:

source_file.c: In function ‘main’:
source_file.c:8:5: warning: trigraph ??< converted to { [-Wtrigraphs]
     ??< puts("Hello Folks!"); ??>
 ^
source_file.c:8:30: warning: trigraph ??> converted to } [-Wtrigraphs]

But when I change the body of main to: 但是,当我改变的机身main以:

<% puts("Hello Folks!"); %>

no warnings are thrown. 没有警告被抛出。

So, Why does the compiler warn me when using trigraphs, but not when using digraphs? 那么, 为什么编译器在使用三字符时会发出警告,但在使用有向图时却没有?

This gcc document on pre-processing gives a pretty good rationale for a warning ( emphasis mine ): 这个关于预处理的gcc文档为警告提供了一个非常好的理由( 强调我的 ):

Trigraphs are not popular and many compilers implement them incorrectly. Trigraphs不受欢迎,许多编译器错误地实现它们。 Portable code should not rely on trigraphs being either converted or ignored. 可移植代码不应该依赖于转换或忽略的三字母。 With -Wtrigraphs GCC will warn you when a trigraph may change the meaning of your program if it were converted . 使用-Wtrigraphs GCC会在三角形可能会改变程序的含义时发出警告。

and in this gcc document on Tokenization explains digraphs unlike trigraphs do not potential negative side effects ( emphasis mine ): 并且在这个关于Tokenization的 gcc文档解释了digraphs不像trigraphs没有潜在的负面影响( 强调我的 ):

There are also six digraphs , which the C++ standard calls alternative tokens, which are merely alternate ways to spell other punctuators. 还有六个有向图 ,C ++标准称之为替代令牌,它们只是拼写其他标点符号的替代方法。 This is a second attempt to work around missing punctuation in obsolete systems. 这是第二次尝试解决过时系统中缺少标点符号的问题。 It has no negative side effects, unlike trigraphs , 与trigraphs不同它没有负面的副作用

Because trigraphs have the undesirable effect of silently changing code. 因为三字母具有静默改变代码的不良影响。 This means that the same source file is valid both with and without trigraph replacement, but leads to different code. 这意味着相同的源文件在有和没有三角形替换的情况下都有效,但会导致不同的代码。 This is especially problematic in string literals, like "<em>What??</em>" . 这在字符串文字中尤其成问题,例如"<em>What??</em>"

Language design and language evolution should strive to avoid silent changes. 语言设计和语言演变应努力避免无声的变化。 Having the compiler warn about trigraphs is a good thing to have. 让编译器警告三字符是一件好事。

Contrast this with digraphs, which were new tokens that do not lead to silent changes. 将此与有向图相比较,有向图是不会导致无声变化的新标记

May be because it has no negative side effects, unlike trigraphs as is stated in gcc documentation: 可能是因为它没有负面的副作用,不像gcc文档中所述的trigraphs:

Punctuators are all the usual bits of punctuation which are meaningful to C and C++. 标点符号是标点符号的常用位,对C和C ++有意义。 All but three of the punctuation characters in ASCII are C punctuators. ASCII中的三个标点符号除了三个标点符号外都是C标点符号。 The exceptions are '@', '$', and '`'. 例外是'@','$'和'`'。 In addition, all the two- and three-character operators are punctuators. 此外,所有两个和三个字符的运算符都是标点符号。 There are also six digraphs, which the C++ standard calls alternative tokens, which are merely alternate ways to spell other punctuators. 还有六个有向图,C ++标准称之为替代令牌,它们只是拼写其他标点符号的替代方法。 This is a second attempt to work around missing punctuation in obsolete systems. 这是第二次尝试解决过时系统中缺少标点符号的问题。 It has no negative side effects, unlike trigraphs, but does not cover as much ground. 与三字母不同,它没有负面的副作用,但没有覆盖那么多的地面。 The digraphs and their corresponding normal punctuators are: 有向图和它们相应的正常标点符号是:

 Digraph:        <%  %>  <:  :>  %:  %:%:
 Punctuator:      {   }   [   ]   #    ##

Trigraphs are nasty because they use character sequences which could legally appear within valid code. Trigraphs很讨厌,因为它们使用的字符序列可以合法地出现在有效的代码中。 A common case which used to cause compiler errors on code for classic Macintosh: 用于在经典Macintosh代码上导致编译器错误的常见情况:

unsigned int signature = '????';  /* Should be value 0x3F3F3F3F */

Trigraph processing would would turn that into: Trigraph处理将把它变成:

unsigned int signature = '??^;  /* Should be value 0x3F3F3F3F */

which would of course not compile. 这当然不会编译。 In some slightly rarer cases, it would be possible for such processing to yield code which would compile, but with different meaning from what was intended, eg 在一些稍微少见的情况下,这样的处理有可能产生可编译的代码,但具有与预期不同的含义,例如

char *template = "????/1234";

which would get turned into 哪个会变成

char *template = "??S4"; // ??/ becomes \, and \123 becomes S

Not the string literal that was intended, but still perfectly legitimate nonetheless. 不是有意的字符串文字,但仍然是完全合法的。

By contrast, digraphs are relatively benign because outside of some possible weird corner cases involving macros, no code containing processable digraphs would have a legitimate meaning in the absence of such processing. 相比之下,有向图是相对良性的,因为除了涉及宏的一些可能的奇怪角落情况之外,没有包含可处理有向图的代码在没有这种处理的情况下将具有合法含义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 gcc 不发出格式警告? - Why doesn't gcc emit a format warning? 有向图是由编译器转换的,而三元图是由预处理器转换的吗? - Are digraphs transformed by a compiler and trigraphs transformed by a preprocessor? 为什么在返回指向局部变量的指针时而不返回局部变量时,gcc会发出警告? - Why does gcc throw a warning when returning a pointer to a local variable and not when returning a local variable? 当初始化不带字符串的const数组时,为什么gcc不会发出警告? - Why gcc does not give a warning when you initialize an array without const with strings? 为什么GCC在将无符号长度设置为2 ^ 64-1时会发出警告? - Why does GCC give a warning when setting an unsigned long to 2^64-1? 在fopen()中使用无效模式时,为什么gcc不会给出警告或错误? - Why gcc does not give a warning or error when invalid mode is used in fopen()? 为什么gcc和clang都没有发出任何警告? - Why gcc and clang both don't emit any warning? 为什么 C 编译器在对负值使用位移时不会发出警告? - Why does a C compiler not throw a warning when using bitshifting on negative value? 为什么gcc没有显示在变量名中使用$的警告消息? - Why is gcc not showing a warning message for using $ in a variable name? 使用gcc返回NULL时没有警告 - No warning when returning NULL with gcc
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM