我有生成以下警告(与SP1 VS2008编译器)这个示例代码:编译器警告为一元运算上无符号整型
警告C4146:施加到无符号类型元负运算 ,结果仍然 无符号
代码:
void f(int n)
{
}
int main()
{
unsigned int n1 = 9;
f(-n1);
}
但由于功能f
将其参数作为int
不应该在没有任何警告的情况下编译此代码?
我有生成以下警告(与SP1 VS2008编译器)这个示例代码:编译器警告为一元运算上无符号整型
警告C4146:施加到无符号类型元负运算 ,结果仍然 无符号
代码:
void f(int n)
{
}
int main()
{
unsigned int n1 = 9;
f(-n1);
}
但由于功能f
将其参数作为int
不应该在没有任何警告的情况下编译此代码?
标准5.3.1/7
一元的操作数 - 操作者 应具有算术或枚举 型,其结果是 其操作数的否定。积分推广是 积分或枚举 操作数。通过从2n中减去 它的值来计算无符号的 数量的负数,其中n是提升的 操作数中的 位数。结果的类型是提升操作数的 类型。
以及关于整体推广的段落4。5/1
类型char,符号的字符, 无符号字符,短整型,或unsigned 短整型的右边的值可以被转换为一个 右值int类型的,如果INT可以 代表的所有值源 类型;否则,源rvalue可以将 转换为类型为 unsigned int的右值。
即一个unsigned int不会被提升为一个int。
如果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
是不可或缺的推广,而unsigned int
- >int
是一个转换
的参数是按值传递的。在函数调用f(-n1)中,在将参数传递给函数之前应用运算符。因此警告。
编译器警告你,将一元减号应用于unsigned int是一件不寻常的事情,并且可能不会给出你期望的结果。在这种情况下得到的结果将相当于在使用32位编译器时调用f(4294967287u)。
请参阅@安德烈亚斯的报价和促销定义的答案:) – 2010-11-24 13:28:50