2010-11-24 36 views
6

我有生成以下警告(与SP1 VS2008编译器)这个示例代码:编译器警告为一元运算上无符号整型

警告C4146:施加到无符号类型元负运算 ,结果仍然 无符号

代码:

void f(int n) 
{ 
} 

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

但由于功能f将其参数作为int不应该在没有任何警告的情况下编译此代码?

回答

12

标准5.3.1/7

一元的操作数 - 操作者 应具有算术或枚举 型,其结果是 其操作数的否定。积分推广是 积分或枚举 操作数。通过从2n中减去 它的值来计算无符号的 数量的负数,其中n是提升的 操作数中的 位数。结果的类型是提升操作数的 类型。

以及关于整体推广的段落4。5/1

类型char,符号的字符, 无符号字符,短整型,或unsigned 短整型的右边的值可以被转换为一个 右值int类型的,如果INT可以 代表的所有值源 类型;否则,源rvalue可以将 转换为类型为 unsigned int的右值。

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

15

如果xunsigned 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是不可或缺的推广,而unsigned int - >int是一个转换

+0

请参阅@安德烈亚斯的报价和促销定义的答案:) – 2010-11-24 13:28:50

2

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

0

编译器警告你,将一元减号应用于unsigned int是一件不寻常的事情,并且可能不会给出你期望的结果。在这种情况下得到的结果将相当于在使用32位编译器时调用f(4294967287u)。