比较对int和unsigned的引用时的警告,但是如果将consts(no ref)与g ++ / msvc进行比较则没有警告

时间:2016-08-23 16:58:50

标签: c++ visual-c++ g++ compiler-warnings

所以我正在编写doctest库,它应该是免费警告。

我最近注意到,在我的if宏内部编写时,没有警告而进入CHECK()语句的代码会造成麻烦。

例如:if(0u == 0)不会引发警告,CHECK(0u == 0);会发出警告。

我调查了一下,部分原因是CHECK()宏背后有模板和表达式分解,并通过const引用捕获。

我的问题是3:

  1. 鉴于这3个片段 - 为什么会发生这种情况?
  2. 发出警告:

    int a = 0;
    unsigned b = 0;
    if(a == b)
    

    没有发出警告:

    const int a = 0;
    const unsigned b = 0;
    if(a == b)
    

    发出警告:

    const int& a = 0;
    const unsigned& b = 0;
    if(a == b)
    
    1. 我怎么打击这个?显然,我可以在库标题中的模板周围使用#pragma diagnostic并使这些警告静音但这不正确。
    2. 原因是如果以下代码发出警告:

      int a = 0;
      unsigned b = 0;
      if(a == b)
      

      然后下一段代码也应该发出警告:

      int a = 0;
      unsigned b = 0;
      CHECK(a == b);
      
      1. 关于const noref案件,我有什么遗漏吗?因为昨天我发布了this问题,这个问题看起来非常相似......是否有其他案例会因为我的模板中的const引用捕获而叮咬我?
      2. 我认为编译器或优化级别不重要 - 我已经尝试了几个版本的g ++ / MSVC(/W4用于msvc而-Wall -Wextra -pedantic + 50 more用于g ++)并且可能clang做同样的事情......

        修改

        以下代码使用g ++生成警告,但未使用msvc ... {-Wsign-conversion

        const int a = -1;
        const unsigned b = 0;
        if(a == b)
        

2 个答案:

答案 0 :(得分:1)

在比较2个变量时,得到警告是完全正常的,一个是有符号的,一个是无符号的。 对于常数,它是不同的:

此代码不会发出警告,因为ab在编译时被评估,并且都被0替换。

获取这段代码并编译它:

const int a = 0;
const unsigned b = 0;
if(a == b)
{
   c =15;
}
else
{
   c=67;
}

 cout << c << endl;

围绕a==b部分进行反汇编:

if(a == b)
{
        c=15;
  1d:   c7 45 f4 0f 00 00 00    movl   $0xf,-0xc(%rbp)
else
{
        c = 67;
}
cout << c << endl;

跳过测试,跳过else ...为什么编译器会发出警告?

开发人员有时会使用此行为来禁用部分代码:在航空业务中,禁止无法访问的代码。此机制确保不生成任何代码。审计可以证明机器代码级别没有死代码。

答案 1 :(得分:1)

通常unsigned int可以表示比int更大的值。虽然您可以将unsigned int转换为int,但有时会失败。例如,在2补码表示法中,-1被转换为unsigned int中的最大数字(假设两者都使用相同大小的容器/寄存器)。

请注意,当您使用const引用时,这是正确的,因为某些引用可以在运行时初始化。例如,当你说一个函数在其参数中有const引用时。你只会在通话时知道它的价值。

另一方面,const intconst unsigned int在编译时已知其值。编译器知道如何转换来自哪个并且没有副作用,因此不需要警告。

如何对抗这种情况?只需使用它们之间相同的类型。如果你真的想使用不同的类型并知道副作用,你可以告诉编译器你知道你在做什么并做一个演员(static_cast)。