无符号整数的一元操作编译警告

7

我有一段生成以下警告的示例代码(使用带有SP1的VS2008编译器):

警告 C4146:对无符号类型应用一元负运算符,结果仍为无符号

代码:

void f(int n)
{
}

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

但是由于函数f将其参数作为int,所以这段代码不应该有任何警告信息才对吧?

4个回答

15
Great! How can I assist you in translating text?
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 是一种转换。


请参考@Andreas的答案,了解“promotion”的引用和定义 :) - Armen Tsirunyan
这适用于值“9”,但我认为通常情况下(int)(-(unsigned)x)-(int)x并不完全相同,因为如果x是INT_MIN,则对其应用减号是未定义的溢出,而对无符号值进行一元减运算对所有无符号值都是定义良好的。如果我错了,请纠正我。 - Nicholas Wilson

13

标准5.3.1/7

一元运算符-的操作数应具有算术或枚举类型,其结果是其操作数的取反。对于整数或枚举类型的操作数进行整数提升。无符号数的负值通过从2的n(n为提升操作数的位数)中减去其值来计算。结果的类型是提升操作数的类型。

Integral Promotion 4.5/1 的段落

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

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


2

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


0
编译器警告您对无符号整数应用一元减运算是不寻常的,可能不会给出您期望的结果。在这种情况下,如果您使用32位编译器,则得到的结果将相当于调用f(4294967287u)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接