【问题标题】:Warning when comparing references to int and unsigned but no warning if comparing consts (no ref) with g++/msvc比较对 int 和 unsigned 的引用时会发出警告,但如果将 consts(无引用)与 g++/msvc 进行比较则不会发出警告
【发布时间】:2016-08-23 16:58:49
【问题描述】:

所以我正在编写 doctest 库,它应该没有警告。

我最近注意到,在我的 CHECK() 宏中编写时,在没有警告的情况下进入 if 语句的代码会导致问题。

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

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

我的问题是 3:

  1. 鉴于这 3 个 sn-ps - 为什么会发生这种情况?

给出警告:

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 并消除这些警告,但这不正确。

原因是如果下面的代码给出警告:

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

那么下一段代码也应该给出警告:

int a = 0;
unsigned b = 0;
CHECK(a == b);
  1. 我对 const noref 案例有什么遗漏吗?因为昨天我发布了this 的问题,这似乎非常相似......是否还有其他案例会因为我的模板中的 const 引用捕获而让我大吃一惊?

我不认为编译器或优化级别很重要 - 我已经尝试了几个版本的 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)

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我决定接受你的回答,尽管我仍然不同意编译器作者的推理......而且我并不完全喜欢这个答案
    【解决方案2】:

    比较 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被跳过...为什么编译器会发出警告?

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多