Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ GCC don'中的断言和未使用局部变量警告;你不能很好地混合吗?_C++_C_Gcc_G++ - Fatal编程技术网

C++ GCC don'中的断言和未使用局部变量警告;你不能很好地混合吗?

C++ GCC don'中的断言和未使用局部变量警告;你不能很好地混合吗?,c++,c,gcc,g++,C++,C,Gcc,G++,我对GCC中未使用的局部变量警告有一个问题 我经常有这样的代码: bool success = foo(); assert(success); 这对于调试构建很好。然而,在发行版中,assert编译为空,GCC给了我一个警告 解决这个问题的最佳方法是什么?用ifdef包装bool success=似乎不是一个好的解决方案…不知道GCC,但这在Microsoft Visual C++中一直有效: (void) success; 它引用变量而不实际执行任何操作。您可以使用标记将其标记为潜在未使用

我对GCC中未使用的局部变量警告有一个问题

我经常有这样的代码:

bool success = foo();
assert(success);
这对于调试构建很好。然而,在发行版中,assert编译为空,GCC给了我一个警告


解决这个问题的最佳方法是什么?用ifdef包装
bool success=
似乎不是一个好的解决方案…

不知道GCC,但这在Microsoft Visual C++中一直有效:

(void) success;

它引用变量而不实际执行任何操作。

您可以使用标记将其标记为潜在未使用。

您可以使用特定于GCC的
未使用属性。它通常被定义为一种简短的形式,很容易从非GCC编译器的代码中删除。

我可能会定义一个特定于此场景的宏

#ifndef NDEBUG
#define verify(expression) assert(expression)
#else
#define verify(expression) expression
#endif
与使用局部变量相比,我更喜欢这种方法,因为它不会用仅条件存在的值污染方法

一般来说,我发现在我的项目中有两组宏非常有用

  • assertXXX:仅调试执行
  • verifyXXX:零售+调试执行

您可以使用
NDEBUG
宏,该宏是在不使用assert时定义的,例如:

#ifndef NDEBUG
  bool success =
#endif
    foo();
  assert(success);
编辑:这将有效地“消除”警告,因为
#ifndef
将确保没有变量可警告。

我使用宏

#define UNUSED(x) ((void)(x))
这样使用:

UNUSED(success);
DEBUG_ONLY( bool success = ) foo();
assert( success );

宏来消除警告并记录变量未使用(至少在某些版本中)的事实是故意的/正常的。

这是Lindydancer的一种稍微简洁的形式,但需要定义一个helper宏。以下是helper宏:

#ifndef NDEBUG
#  define DEBUG_ONLY( ... ) __VA_ARGS__
#else
#  define DEBUG_ONLY( ... )
#endif
然后可以这样使用:

UNUSED(success);
DEBUG_ONLY( bool success = ) foo();
assert( success );

foo()是否纯粹为调试返回值?只有在定义特殊宏/变量(如
NDEBUG
)时,才会忽略AFAIK断言。如果没有定义,断言应该在两种模式下都能工作。Mh,让函数返回一个
bool
以指示成功或失败,只检查调试版本,并假设它在发布模式下成功。
assert(!success)
表示您希望断言存在故障……但这不是滥用断言吗?作为一名维护程序员,我会发现这种非自我记录和混乱。对我的断言旨在检查代码是否被正确调用,而不是子系统是否仅在调试构建中失败。这也违反了测试你飞什么,测试你飞什么。如果你只是想在releae代码中忽略它,为什么还要返回bool呢?至少在发生故障时,在被调用的方法中使用断言会更好。在您的示例中,如果没有日志机制,我经常将错误条目推送到最后一个可用的队列槽中。这很好,但有一个缺点,即如果
expression
包含函数调用,它们可能不会被优化。@Oli,这是怎么回事?我不知道如何优化它,因为在调试中,它将通过assert强制调用,而在非调试中,函数调用只是独立的,无法优化。@Jared:这就是我的观点。如果您不需要调用函数,而只需要计算将要断言的值,该怎么办?另外,至少在带有
-Wall
的GCC中,一个独立表达式(在非调试模式下)会引发一个警告/错误,这会将我们带回到我们开始的地方@在这种情况下,您应该直接使用assert。断言和验证之间的区别是1)仅调试断言2)调试和非调试断言。@Jared:这是OP试图解决的问题。问题不是它没有得到优化,而是GCC抛出了一个警告。这将有效地“杀死”警告,因为
#ifndef
将确保没有变量需要警告。太棒了!8-)我在我的一个库中遇到了这个问题,它的头中有一个静态变量定义,但并不总是被使用。虽然这并不能很好地回答这个问题,因为程序员想要一个能与g++和cl一起工作的解决方案……不过,实际上这个问题是特定于GCC的!8-)我和我猜之前读过的另一本书混在一起了。太完美了。