繁体   English   中英

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

[英]Why does C++ allow implicit conversion from int to unsigned int?

考虑以下代码:

void foo(unsigned int x)
{

}

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

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

简短的回答是因为 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 的向后兼容性,继续允许这种隐式转换。

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

任你选。

@user168715 是对的。 C++ 最初被设计为 C 的超集,假装尽可能向后兼容。 “C”哲学是将大部分责任交给程序员,而不是禁止危险的事情。 对于 C 程序员来说,它是天堂,对于 Java 程序员来说,它是地狱……只是口味问题。

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

我也同意某些继承的自由会导致非常难以调试的错误,所以我补充说在 g++ 中你可以打开警告以防止你犯这种错误: -Wconversion标志.

-W转换

警告可能改变值的隐式转换。 这包括实数和整数之间的转换,例如 x 为 double 时的 abs(x); 有符号和无符号之间的转换,如无符号 ui = -1; 并转换为更小的类型,例如 sqrtf (M_PI)。 不要警告像 abs ((int) x) 和 ui = (unsigned) -1 这样的显式强制转换,或者如果值没有被 abs (2.0) 中的转换更改。 可以使用 -Wno-sign-conversion 禁用有关有符号和无符号整数之间转换的警告。

对于 C++,还警告用户定义转换的重载解析混乱; 以及永远不会使用类型转换运算符的转换:转换为 void、相同类型、基类或对它们的引用。 在 C++ 中默认禁用有关有符号和无符号整数之间转换的警告,除非显式启用 -Wsign-conversion。

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

到最初的 C 标准时,许多(全部?)编译器已经允许转换。 基于 C 的基本原理,似乎很少(如果有的话)讨论是否应该允许这种隐式转换。 到 C++ 出现时,这种隐式转换已经非常普遍,消除它们会导致该语言与大量 C 代码不兼容。 可能会使 C++ 更干净; 肯定会减少它的使用——以至于它可能永远不会超越“C with Classes”阶段,甚至这只是贝尔实验室历史上一个几乎被忽视的脚注。

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

无符号保留规则说您将两者都提升为无符号整数。 值保留规则说,如果它可以表示原始类型的所有值(例如,8 位 char、16 位 short 和 32 位 int 的常见情况),则将这两个值提升为int 另一方面,如果 int 和 short 都是 16 位,因此 int 不能表示 unsigned short 的所有值,那么您将 unsigned short 提升为 unsigned int(请注意,它仍然被视为提升,即使它仅在它真的发生时发生不是促销——即两种类型的大小相同)。

不管是好是坏,(这两个方向都被争论了很多次)委员会选择了保值而不是未签名的保值促销。 但是请注意,这涉及相反方向的转换:而不是从有符号到无符号,而是关于您是否将无符号转换为有符号。

因为标准允许从有signed类型到unsigned类型的隐式转换。

(int)a + (unsigned)b结果为unsigned - 这是一个 c++ 标准。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM