对unsigned int进行一元操作的编译器警告

时间:2010-11-24 13:18:16

标签: c++ compiler-warnings unsigned

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

  

警告C4146:一元减运算符   应用于无符号类型,结果仍然存在   无符号

代码:

void f(int n)
{
}

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

但是因为函数f将它的参数作为int而不应该编译而没有任何警告?

4 个答案:

答案 0 :(得分:15)

如果x属于unsigned int类型,则-x也是如此,它实际上等同于2n-x(其中n最有可能是32)。要避免警告获得正确的行为,请转为int

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

我建议阅读C ++标准的“表达式”一章。您会在-x表达式x中看到整数促销活动发生在int上,这意味着几乎所有内容都会提升为unsigned 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

但是int - &gt; unsigned int是不可或缺的促销,而int - &gt; {{1}}是转化

答案 1 :(得分:12)

标准5.3.1 / 7

  

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

关于积分推广4.5 / 1的段落

  

char类型的rvalue,signed char,   unsigned char,short int或unsigned   short int可以转换为   如果int可以,则为int类型的rvalue   表示源的所有值   类型;否则,源rvalue可以   转换为类型的右值   unsigned int。

即。 unsigned int不会被提升为int。

答案 2 :(得分:2)

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

答案 3 :(得分:0)

编译器警告你将unary减号应用于unsigned int是一件不寻常的事情,可能无法给出你期望的结果。如果您使用的是32位编译器,那么在这种情况下得到的结果将等同于调用f(4294967287u)。