【问题标题】:GHS C++: extra semicolon diagnostic message - purpose?GHS C++:额外的分号诊断消息 - 目的?
【发布时间】:2015-07-31 09:39:46
【问题描述】:

GHS 编译器中,如果您连续有多个分号而没有任何中间语句,则会生成诊断消息(警告)。例如:

void myfunc()
{
}; // warning #381-D: extra ';' ignored.

这似乎不是很常见的情况,但在预处理发生后也会发出此警告,因此,以下也会产生警告(在发布时编译时):

#if _DEBUG
  #define DEBUG_VAR(x) x
#else
  #define DEBUG_VAR(x) 
#endif

void myfunc()
{
}
// global variable, used only in debug
DEBUG_VAR(int x); // warning #381-D: extra ';' ignored.

我意识到在这种情况下有一些简单的方法可以解决这个问题,这只是一个说明性示例。在预处理器的许多其他情况下,您最终可能会得到类似的构造。

显然,代码是合法的 c++,我从未在我使用过的任何其他编译器上遇到过这样的警告消息。是否有一些合理的解释说明为什么此警告会有所帮助,例如,是否存在此警告可能指示编程错误的特定情况?

【问题讨论】:

  • GCC's always done it as far as I can remember。也许您一直没有指定警告开关? :)
  • @LightnessRacesinOrbit 也许我只是在使用 gcc 编译时没有使用 -pendantic。我没有向 GHS 指定这一点,它通常会发出警告。
  • “显然,代码是合法的 c++” - 这既不明显也不真实。在添加“空声明”产生的 C++11 之前,函数外部的杂散分号实际上在技术上是非法的,尽管我听说过的所有编译器都接受它作为扩展。
  • @SebastianRedl - 查看 C++03 规范 - 似乎说空语句是合法的:6.2 表达式语句 1 表达式语句的形式为 expression-statement: expressionopt ;计算表达式并丢弃其值。左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换不适用于表达式。表达式语句的所有副作用都在执行下一条语句之前完成。缺少表达式的表达式语句称为空语句。
  • @MuertoExcobito 声明!= 声明。语句出现在函数体中,所以有杂散的分号是合法的。在文件(或命名空间或类)级别,编译器仅查找声明。

标签: c++ greenhills


【解决方案1】:

我最喜欢的例子是“持久分号”。我们在我最后一个工作的地方有一个。他写了两次以上:

for (i=0; i<MAX; ++i);
    a[i] = 0;

...然后因为他的数组没有初始化而受阻。而且更糟糕的,他有一个随机变量被破坏的错误。

如果你不能发现它,如果编译器发现它不是很好吗?

说了这么多,我同意一个杂散的分号通常是“驯服的”——但是让编译器在一个地方吐出错误的逻辑并没有区分其他地方......

【讨论】:

  • 这个代码示例不会抛出警告,因为在这种情况下分号实际上做了一些事情。
  • @MuertoExcobito 同意。虽然这个例子显然是不正确的,但它纯粹是合法的 C,并且需要一个静态分析程序来突出越界访问 - 编译器必须假设它是故意的。我的意思是更多地强调人们会在可能的情况下添加编译器应该警告的杂散分号。他确实犯了比上面更严重的错误,但我就是想不出一个好的例子。在他花了三个小时寻找之后,我花了三分钟才找到每次
  • 嗯,听起来确实像 PITA……但是,这并不是我问题的真正答案。如果 -Wempty-body 用于 for 循环(对于您的情况),那就太好了,但是唉。
【解决方案2】:

是否有一些合理的解释说明为什么此警告会有所帮助,例如,是否存在此警告可能指示编程错误的特定情况?

肯定是大多数情况?

由于; 没有任何意义,要么你把它写成冗余(然后你必须问“为什么?”)或者——这是关键——你不小心删除了它之前的一些代码,或者由于出现其他错误而使解析器感到困惑并使; 看起来看起来是多余的,而实际上并非如此。

不过,我想不出一个例子。

但是那个宏最好这样写:

#include <type_traits>
#ifndef NDEBUG
   #define DEBUG_VAR(T, N) std::common_type<T>::type N;
#else
   #define DEBUG_VAR(T, N)
#endif

void myfunc()
{}

// global variable, used only in debug
DEBUG_VAR(int, x)

【讨论】:

  • 我同意,分号是无用的,但正如我的示例所展示的,有一个使用预处理宏的非常常见的示例,您最终会在代码中使用这种模式。在另一种配置中预处理的代码可能没有额外的分号,这似乎是有额外分号的更常见的原因。
  • @MuertoExcobito:我不认为这是“常见的”,我会指导例如实习生,初级开发人员不要这样做。分号不应该在那里,故事结束。我的回答中讨论冗余的部分解决了这种用法。
  • 此代码示例是从我的代码库中简化而来,但基于我收到此警告的真实情况。如果_DEBUG 未定义,则不需要分号,即您正在发行版中编译,并且会给出此警告。
  • @MuertoExcobito:它不应该在那里。你的宏很糟糕。
  • @LightnessRacesinOrbit 我非常不同意你的观点。仅仅因为有一个宏并不意味着我们应该放弃常见的 C++ 语法,而常见的 C++ 语法是用分号结束没有大括号的声明(甚至有些有大括号)。因此,DEBUG_VAR(int, x); 优于 DEBUG_VAR(int, x)。在第二种情况下,原始代码编辑器会同意并为自动缩进做一些奇怪的事情。解决这个问题的正确方法是在发布案例中将宏定义为无害的东西,例如static_assert(true, "") 在 C++11 中。
猜你喜欢
  • 1970-01-01
  • 2015-02-11
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多