C++ 为什么C++;允许从整数到无符号整数的隐式转换?
考虑以下代码:C++ 为什么C++;允许从整数到无符号整数的隐式转换?,c++,C++,考虑以下代码: void foo(unsigned int x) { } int main() { foo(-5); return 0; } 编译没有问题。这样的错误会导致很多问题,而且很难找到。为什么C++允许这样的转换?< p>简短的答案是因为C最初支持这样的转换,他们不想在C++中破坏现有的软件。 请注意,某些编译器会对此发出警告。例如,g++-Wconversion将对该构造发出警告 在许多情况下,隐式转换是有用的,例如,当计算中使用int时,但最终结果永远不会是负数(从算
void foo(unsigned int x)
{
}
int main()
{
foo(-5);
return 0;
}
编译没有问题。这样的错误会导致很多问题,而且很难找到。为什么C++允许这样的转换?< p>简短的答案是因为C最初支持这样的转换,他们不想在C++中破坏现有的软件。 请注意,某些编译器会对此发出警告。例如,
g++-Wconversion
将对该构造发出警告
在许多情况下,隐式转换是有用的,例如,当计算中使用int
时,但最终结果永远不会是负数(从算法中知道,并且可以选择断言)
<>编辑:附加的可能解释:记住,原来C是一种比C++更松散的类型语言。如果使用K&R风格的函数声明,编译器将无法检测此类隐式转换,那么为什么还要在语言中限制它呢。例如,您的代码大致如下所示:
int foo(x)
unsigned int x
{
}
int main()
{
foo(-5);
return 0;
}
而声明本身就是intfoo(x)代码>
编译器实际上依靠程序员将正确的类型传递到每个函数调用中,并且在调用站点上没有进行转换。然后,当函数实际被调用时,堆栈(etc)上的数据将按照函数声明指示的方式进行解释
一旦编写了依赖于这种隐式转换的代码,即使在函数原型中添加了实际的类型信息,也很难将其从ANSI C中删除。这可能就是为什么它现在仍然保持在C中。然后C++不断地决定不破坏C的向后兼容性,继续允许这种隐式转换。UL>
这只是一种语言的另一个怪癖,它有许多愚蠢的怪癖
转换被很好地定义为环绕,这在某些情况下可能很有用
它与C向后兼容,这是因为上面的原因
您可以选择。因为该标准允许从有符号
到无符号
类型的隐式转换
< > >代码>(int)A+(无符号)B<代码>结果为<代码>未签名< /代码> -这是C++标准。 < P> @ USE16815是正确的。C++最初被设计成C的超集,假装尽可能向后兼容。
“C”理念是将大部分责任交给程序员,而不是拒绝危险的事情。对于C程序员来说,这是天堂,对于Java程序员来说,这是地狱。。。品味问题
我将挖掘标准,看看它到底写在哪里,但我现在没有时间做这件事。我会尽快修改我的答案
我也同意一些继承的自由可能会导致很难调试的错误,因此我补充说,在g++中,您可以打开一个警告来防止犯这种错误:-Wconversion
标志
警告可能改变值的隐式转换。这包括
实数和整数之间的转换,
与abs(x)一样,当x是双的时候;
有符号和有符号之间的转换
unsigned,比如unsigned ui=-1;和
转换为较小的类型,如
sqrtf(M_-PI)。不要发出明确警告
像abs((int)x)和ui这样的强制转换=
(无符号)-1,或者如果值不是
通过类似abs的转换进行更改
(2.0). 关于转换的警告
在有符号整数和无符号整数之间
可以通过使用禁用
-Wno符号转换
对于C++,还警告用户定义的过载解决方法
转换;以及将要进行的转换
切勿使用类型转换运算符:
转换为void,同一类型,a
基类或对它们的引用。
关于之间转换的警告
有符号整数和无符号整数是
在C++中默认为禁用
-Wsign转换已显式启用
其他编译器可能有类似的标志。在最初的C标准出现时,许多(所有?)编译器已经允许这种转换。基于C的基本原理,似乎很少(如果有的话)讨论是否应该允许这种隐式转换。当C++出现时,这种隐式转换非常普遍,消除它们会使语言与大量C代码不兼容。它可能会使C++更干净;这肯定会使它少用很多——以至于它可能永远也不会超越“C带类”阶段,甚至这也只是贝尔实验室历史上一个被忽视的脚注
这条线上唯一真正的问题是在提升“小于”int的无符号值时,“保留值”和“保留无符号”规则之间的区别。当(例如)向无符号字符添加了一个无符号短字符时,就会出现这两个规则之间的区别
无符号保留规则表示将两个值提升为无符号整数。值保留规则表示将两个值提升为int
,前提是它可以表示原始类型的所有值(例如,常见的8位字符、16位短字符和32位整数)。另一方面,如果int和short都是16位,那么int不能表示unsigned short的所有值,那么可以将unsigned short提升为unsigned int(注意,它仍然被视为提升,即使它只发生在实际上不是提升的情况下——即,这两种类型的大小相同)
不管是好是坏,(这两个方向已经争论了很多次)委员会选择了保留价值而不是保留未签名的促销。但是,注意,这是一个相反的转换:不是从签名到无符号,而是关于是否将未签名转换为签名。陈腐的答案:因为C++被设计成(主要)向后兼容C,而C允许在积分之间隐式转换。