代码之家  ›  专栏  ›  技术社区  ›  Naveen

对无符号int执行一元操作的编译器警告

  •  6
  • Naveen  · 技术社区  · 14 年前

    我有这个示例代码,它生成以下警告(带有SP1的VS2008编译器):

    警告C4146:一元减号运算符 应用于无符号类型,结果仍为 未签名的

    代码:

    void f(int n)
    {
    }
    
    int main()
    {
        unsigned int n1 = 9;
        f(-n1);
    }
    

    但因为函数 f 把它的参数作为 int 这段代码不应该在没有任何警告的情况下编译吗?

    4 回复  |  直到 11 年前
        1
  •  12
  •   Matthieu M.    14 年前

    标准5.3.1/7

    一元运算符的操作数 应具有算术或计数 类型和结果是否定 它的操作数。整体提升是 在积分或枚举上执行 操作数。无符号的负数 数量是通过减去 它的值来自2n,其中n是 提升中的位数 操作数。结果的类型是 提升的操作数的类型。

    以及关于整体推广的段落4.5/1

    char、signed char类型的右值, 无符号字符、短整型或无符号 short int可以转换为 int类型的右值,如果int可以 表示源的所有值 类型;否则,源右值可以 转换为类型的右值 无符号INT.

    即,无符号int不会提升为int。

        2
  •  15
  •   Eitan T lattimore    11 年前

    如果 x 属于类型 unsigned int 然后就是 -x 它实际上相当于 2 n -x (何处) n 最有可能是32)。为了避免警告 获得正确的行为,投射到 int :

    f(-static_cast<int>(n));
    

    我建议阅读C++标准的“表达式”一章。在这里,你会在表达式中看到 -X 整体促销活动在 X 这意味着几乎所有的东西都会被提升到 int 但是 无符号整型 不是。

    看看这个非常有趣的例子:

    template<class T>
    void f(T x)
    {
      //somehow print type info about x, e.g. cout << typeid(x).name() or something
    }
    
    int main()
    {
      char x;
      f(x);
      f(+x);
      f(-x);
    }
    

    印刷品:

    char
    int 
    int
    

    但是 char -gt; int 是整体提升,而 无符号整型 -gt; int 是一个转换

        3
  •  2
  •   JP19    14 年前

    参数是传递值。在函数调用f(-n1)中,在将参数传递给函数之前应用运算符。因此发出警告。

        4
  •  0
  •   dc42    14 年前

    编译器警告您,将一元减号应用于无符号int是一件不寻常的事情,可能无法给出预期的结果。如果您使用的是32位编译器,那么在这种情况下得到的结果相当于调用F(4294967287U)。