为什么缺少终止“字符是警告?

时间:2017-11-16 13:18:34

标签: c gcc compiler-errors compilation compiler-warnings

例如,当我们编译以下代码时:

printf("hello);

我们收到警告,然后发现有关丢失的"字符的错误。在我看来,警告告诉我们一个可以编译的代码,但其行为可能与开发人员期望的不同。因此,我的理解错过了两件事:

  1. 是否有完整的代码可以在包含这样一部分代码时编译而没有错误。
  2. 如果这样的代码不存在,为什么这个缺失的字符情况不会给我们一个错误(不是警告+错误)。
  3. 编辑(我正在尽力处理偏离主题的投票建议):
    1.所需行为:只有一条错误诊断消息,不需要对同一事件发出警告。

    1. 其他相关问题不允许我接受第一个答案:
    2. 2.1 printf_s()是否有同样的问题?我试图启用-c11选项但没有成功。

      2.2发出警告的历史原因在我看来似乎并不合理,因为在类似的情况下为什么没有使用这种双重信息(在新的c版本中禁止使用旧的结构)。

2 个答案:

答案 0 :(得分:4)

  

在我看来,警告告诉我们可以编译的代码   但是他的行为可能与开发者的行为有所不同   预计。因此,我的理解错过了两件事:

您的意见与此无关,C标准和C ++标准都不区分不同类别的诊断消息。事实上,许多编制者确实区分了一种基于历史的惯例,尽管这是一种广泛观察到的惯例。最重要的是你的编译器通过这种区分意味着什么(如果它确实是一个)。另一方面,幸运的是,GCC确实采用了与您描述的类似的约定,如记录in its manual

  
      
  • 错误报告无法编译程序的问题。 [...]。

  •   
  • 警告报告代码中可能表示存在问题的其他异常情况,尽管编译可以(并且确实)继续进行。 [...]

  •   

(GCC 7.2手册,第13.9节;相同或类似的文本也出现在手册的早期版本中,至少回到第4节。)

请注意,文档对警告的含义略有不同:GCC警告表示编译可以继续,但无法保证它可以成功完成。如果确实最终不能,那么我希望GCC根据其文档也发布错误诊断。这正是我在这个测试程序中观察到的,无论是编译为C还是C ++:

#include <stdio.h>

int main(void) {
    printf("hello);
}

我真的认为你在过多的事实是GCC除了在这种情况下发生错误之外还会发出警告。这是一个没有特别重要意义的实施怪癖。

  
      
  1. 是否有完整的代码可以在包含这样一部分代码时编译而没有错误。
  2.   

这完全取决于你的意思。琐碎的是,我可以在上面的程序中用//作为错误行的前缀,将它变成注释,这将使它成为完全有效的C和C ++源代码。我可以添加到给定源的多种其他方式,而不删除任何使其有效的方法 - 其中一些甚至会产生一个实际执行printf()调用的程序。

我想你真正想知道的是,是否有代码可以引起GCC的警告而不是相应的错误。据我所知,现代GCC不提供这样的代码,但historically, GCC did allow it作为扩展,以字符串文字中嵌入的,未转义的换行符的形式出现:

    printf("hello);
    Goodbye");

该行为已在GCC 3.2中弃用,并且早在GCC 4(当前为7.2)时就被删除了。

  
      
  1. 如果这样的代码不存在,为什么这个缺失的字符情况不会给我们一个错误(不是警告+错误)。
  2.   

我们只能猜测,但它似乎可能源于上述语言扩展的历史存在。而且,你做的太多了。 GCC针对同一问题发出了两个诊断信息 - 那又怎么样?诊断的最终目的是帮助您弄清楚代码的错误或错误,GCC在这种情况下发出的诊断就可以完成这项工作。

答案 1 :(得分:1)

您的编译器在检测到程序格式错误时可能会发出错误,并描述程序在其发生位置无法正常形成的直接原因。

这通常是无用的,因为这个错误可能已经走了很多行。

它还会发出猜测(通常是有根据的猜测)实际导致问题的警告。也许您忘记了前一行的;,未能关闭{(。警告不是&#34;这个标记是错误点#34;而是#34;这是一切都出错的地方&#34;。

实际上,C ++标准本身并不区分警告和错误;他们都是诊断。它要求某些事情导致诊断,并且不禁止编译器发出其他诊断信息。编译器甚至可以通过警告自由编译生成错误的程序。

我希望&#34;字符串&#34;中的换行符出错,然后是指向公开引用的警告。