【问题标题】:Portable UNUSED parameter macro used on function signature for C and C++用于 C 和 C++ 的函数签名的可移植 UNUSED 参数宏
【发布时间】:2020-11-22 10:23:45
【问题描述】:

我有兴趣创建一个宏来消除未使用的变量警告。

这个问题描述了一种通过在函数代码中编写宏来抑制未使用参数警告的方法:

Universally compiler independent way of implementing an UNUSED macro in C/C++

但我对可以在函数签名中使用的宏感兴趣:

void callback(int UNUSED(some_useless_stuff)) {}

这是我用 Google 挖出来的 (source)

#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#elif defined(__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
#elif defined(__cplusplus)
# define UNUSED(x)
#else
# define UNUSED(x) x
#endif

这可以针对其他编译器进一步扩展吗?

编辑:对于那些不明白标记是如何工作的人:我想要一个同时适用于 C 和 C++ 的解决方案。这就是为什么这个问题同时被标记为 C 和 C++,这就是为什么不能接受仅 C++ 的解决方案。

【问题讨论】:

  • 有一个更简单的方法,在 C++ 中你可以省略参数名。
  • @john 是的,在 C++ 中可以。在C中你不能。我已经修改了宏。
  • 如果您对 C++ 答案不感兴趣,请不要标记您的问题 C++
  • 关于未使用变量的警告是可选功能,因此禁用该警告的方法也是可选的,因此肯定有一些编译器无法做到这一点
  • @jk 我对只适用于 C++ 的答案不感兴趣。

标签: c++ c macros warnings


【解决方案1】:

我的做法是这样的:

#define UNUSED(x) (void)(x)
void foo(const int i) {
    UNUSED(i);
}

我在 Visual Studio、Intel、gccclang 中没有遇到过这个问题。

另一种选择是只注释掉参数:

void foo(const int /*i*/) {
  // When we need to use `i` we can just uncomment it.
}

【讨论】:

  • 第一个答案解决了一个完全不同的问题,第二个解决方案仅适用于 C++。
  • 强制转换为 void 也适用于未使用的变量,未使用的函数甚至 (void)printf。通过在函数签名中标记参数来泄露实现细节一开始就很有趣。
【解决方案2】:

只是一件小事,最好将__attribute__((__unused__)) 用作__attribute__((unused)),因为未使用的地方可以定义为宏,我个人对这种情况有一些问题。

但我使用的技巧是:

#define UNUSED(x) (void)x;

但它仅适用于方法的变量和参数,而不适用于函数本身。

【讨论】:

  • 有些编译器会处理“(void)x;”仍然未使用。以迪亚布为例。
【解决方案3】:

经过cmet测试和跟踪,问题中提到的原始版本证明已经足够了。

使用:#define UNUSED(x) __pragma(warning(suppress:4100)) x(在 cmets 中提到),可能是在 MSVC 上编译 C 所必需的,但这是一个奇怪的组合,我最后没有包含它。

【讨论】:

  • 这就是我所缺少的。我实际上使用#define UNUSED(x) __pragma(warning(suppress: 4100 4101)) x 来装饰未使用的函数参数和局部变量(__attribute__((unused)) 在 g++ 中的工作方式相同)。超级酷!
  • 这对我的 MSVC2013 不起作用,仍然收到C4100 警告。
  • 出于好奇,您为什么选择这个而不是@MattClarkson 的回答?与简单的 (void)x 相比,这肯定不那么便携。
  • 我知道我为什么要朝这个方向发展:我在 constexpr 函数中有未使用的参数(在 VS2015 中)不能有多个语句。
【解决方案4】:

在许多编译器中,我使用了以下内容,不包括对 lint 的支持。

#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
#       define PGM_GNUC_UNUSED         __attribute__((__unused__))
#else
#       define PGM_GNUC_UNUSED
#endif

经过测试的编译器:GCC、Clang、EKOPath、Intel C Compiler / Composer XE、Cygwin / Linux / MSYS 上的 MinGW32、Cygwin / Linux 上的 MinGW-w64、Sun ONE Studio / Oracle Solaris Studio、Visual Studio 2008 / 2010。

示例用法:

pgm_tsc_init (
        PGM_GNUC_UNUSED pgm_error_t**   error
        )
{
...
}

PGM 是这个基于 C 的项目的标准前缀。 GNUC 是 GLib 对该属性的约定。

我认为在某些情况下编译会警告__attribute__,但肯定不会出错。

【讨论】:

  • 你确定吗?我不认为MSVC实际上定义了__GNUC__宏,那会很奇怪。
  • @Let_Me_Be: 如果不是,那么在#if 条件的上下文中,就好像__GNUC__ 被定义为等于0。所以你会得到#else 分支,Steve-o 已对其在 Visual Studio 2008 和 2010 上进行了测试。不一定与您使用的警告级别相同。
  • @Let_Me_Be 这就是 Cygwin 和 Mingw 使用它但 MSVC 没有使用它的原因,最终结果是 Debian 4 / RHEL 4 和更新版本的工作系统。
  • @Steve-o 好吧,那么这个解决方案是倒退了一步,因为它只适用于 GCC。它不会抑制任何其他编译器上的警告。
  • 根据 ftp.gnu.org/old-gnu/gcc> 的文档,第一个接受 __attribute__((unused)) 的 GCC 版本是 2.7,而不是 2.5。
猜你喜欢
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
相关资源
最近更新 更多