为什么C ++允许从int到unsigned int的隐式转换?

时间:2011-03-10 17:16:26

标签: c++

请考虑以下代码:

void foo(unsigned int x)
{

}

int main()
{
  foo(-5);
  return 0;
}

编译没有问题。像这样的错误可能会导致很多问题并且很难找到。为什么C ++允许这样的转换?

5 个答案:

答案 0 :(得分:20)

简短的回答是因为C最初支持这样的转换,并且他们不想破坏C ++中的现有软件。

请注意,有些编译器会对此发出警告。例如,g++ -Wconversion将警告该构造。

在许多情况下,隐式转换很有用,例如在计算中使用int时,但最终结果永远不会为负(从算法中得知并且可选地断言)。

编辑:其他可能的解释:请记住,最初的C语言是一种比C ++更宽松的语言。使用K& R样式函数声明,编译器无法检测到这种隐式转换,因此为什么要在语言中限制它。例如,您的代码看起来大致如下:

int foo(x)
unsigned int x
{

}

int main()
{
  foo(-5);
  return 0;
}

虽然宣言本身就是int foo(x);

编译器实际上依赖程序员将正确的类型传递给每个函数调用,并且在调用站点没有进行转换。然后,当函数实际被调用时,堆栈上的数据(等)被解释为函数声明指示的方式。

一旦编写了依赖于那种隐式转换的代码,即使函数原型添加了实际类型信息,也很难将其从ANSI C中删除。这可能就是为什么它现在仍然存在于C中。然后C ++出现并再次决定不破坏与C的向后兼容性,继续允许这种隐式转换。

答案 1 :(得分:6)

  • 只是另一种语言的怪癖,有很多愚蠢的怪癖。
  • 转换定义明确,以便在某些情况下使用。
  • 它与C向后兼容,由于上述原因,它就是这样做的。

选择。

答案 2 :(得分:4)

@ user168715是对的。 C ++最初设计为C的超集,假装尽可能向后兼容。 “C”的理念是将大部分责任交给程序员,而不是放弃危险的事情。对于C程序员来说,它是天堂,对于Java程序员来说,它是地狱......一个品味问题。

我会挖掘标准,看看它的确切位置,但我现在没有时间做这件事。我会尽快编辑我的答案。

我也同意一些继承的自由可能会导致很难调试的错误,所以我在g ++中添加了说法,你可以打开一个警告来阻止你做这种错误: -Wconversion旗帜。

  

-Wconversion

     

警告可能会改变值的隐式转换。这包括   实数和整数之间的转换,   像x是双倍时的abs(x);   签名和签名之间的转换   unsigned,如unsigned ui = -1;和   转换为较小的类型,例如   sqrtf(M_PI)。不要警告明确   像abs((int)x)和ui =的强制转换   (无符号)-1,或者如果值不是   由转换改变,如在abs   (2.0)。有关转化的警告   有符号和无符号整数之间   可以使用禁用   -Wno-符号转换。

     

对于C ++,还要警告用户定义的混乱重载分辨率   转换;和转换将会   从不使用类型转换运算符:   转换为无效,相同的类型,a   基类或对它们的引用。   有关转换的警告   有符号和无符号整数   默认情况下在C ++中禁用,除非   -Wsign-conversion明确启用。

其他编译器可能有类似的标志。

答案 3 :(得分:0)

到原始C标准时,许多(所有?)编译器已经允许转换。根据C的基本原理,似乎很少(如果有的话)讨论是否应该允许这种隐式转换。当C ++出现时,这种隐式转换非常普遍,消除它们会使语言与大量C代码不兼容。它可能使C ++更清洁;它当然使得它的使用更少 - 到了它可能永远不会超越“C with Classes”阶段,甚至那只是一个被忽略的脚注贝尔实验室的历史。

在推广无符号值“小于”int时,沿着这一行的唯一真正问题是“保留值”和“无符号保留”规则。当你(例如)将unsigned short添加到unsigned char时,会出现两者之间的差异。

无符号保留规则表示你将两者都提升为unsigned int。值保留规则表示您将两个值都提升为int如果它可以表示原始类型的所有值(例如,8位字符的常见情况,16位短,和32位int)。另一方面,如果int和short都是16位,那么int不能表示unsigned short的所有值,那么你将unsigned short提升为unsigned int(注意它仍然被认为是一个提升,即使它只发生在它真的促销 - 即两种类型的尺寸相同。)

无论好坏,(并且多次双向争论)委员会都选择了保值而不是未签约的保留促销。但请注意,这会处理相反方向的转换:而不是从有符号转换为无符号转换,而是将无符号转换为有符号转换。

答案 4 :(得分:-1)

因为该标准允许从signedunsigned类型的隐式转换。

同样(int)a + (unsigned)b会产生unsigned - 这是c ++标准。