【问题标题】:How many times does the type conversion happen in the following code?以下代码中发生了多少次类型转换?
【发布时间】:2020-07-10 10:25:40
【问题描述】:

我正在研究自动类型转换(自动转换),并得出以下代码。

char a = 10, b = 5;
int res;
res = a / b;

我认为自动转换只发生了 2 次(char a 转换为 intchar b 转换为 int)。 但据说答案是4次。

有人能解释一下为什么自动类型转换会发生 4 次吗?

【问题讨论】:

  • 在初始化中,105 都被转换为char。在a / bab 中转换为int

标签: c type-conversion


【解决方案1】:

请注意,正确的术语是conversionconversion 可以是隐式的(如果由编译器静默执行),也可以是显式的(通过程序员编写的强制转换运算符)。强制转换始终是显式转换。

这里确实发生了几个隐式转换。请注意,像 10 这样的整数常量在表达式中被视为 int 变量。

  • a = 10 通过赋值从intchar 进行隐式转换。
  • b = 5 通过赋值从intchar 进行隐式转换。
  • a 中的 a / b 是提升为 int 的整数,作为通常的算术转换的一部分。
  • b 中的 a / b 是提升为 int 的整数,这是通常的算术转换的一部分。

a / b 的结果则为int 类型,与= 左操作数res 的类型相同,因此无需进一步转换。

详情请见Implicit type promotion rules

【讨论】:

  • 所以基本上,为了让整数'10'(4byte)适应字符类型'a'(1或2byte),整数必须转换成字符?所以,'a'和'b'这两个字符是要各自转换成整数,以便计算?对吗?
  • @Learner_15 是的,没错。虽然请注意,C 中的字符类型始终为 1 个字节(尽管理论上 1 个字节可以大于 8 位)。
【解决方案2】:

真正发生的事情取决于编译器的实现。应该发生的是 8 位乘 8 位除法并将结果转换为 int(16 位或 32 位,这取决于目标体系结构和编译器)。

由于 CPU 通常没有 8 位除法指令,编译器可能会将其解释为:

res = (int)(char)((int)a / (int)b)

char 类型通常应该是 8 位有符号整数,实际上编译器可以将其优化为:

res = (int)a / (int)b

“res = (int)a / (int)b”优化是正确的,如果 char 被视为无符号(这是编译器的属性)。如果 char 在您的实现中已签名,则 -128 / -1 给出 +128,这不能由 signed int 表示。

实际上 char 在某些编译器中是有符号的,而在其他编译器中是无符号的。最好不要对字符执行数学运算。最好尽快将其转换为明确的内容。

如果您不确定您的编译器实现和设置是什么,尤其是在“边缘情况”中,请对其进行测试。如果您想要可移植的代码,请避免不确定性。在这种情况下,最好使用显式类型转换来避免“边缘情况”。无论如何都应该避免除以零。

【讨论】:

  • 不,这不依赖于编译器,各种隐式提升规则是可移植的,唯一不可移植的是int的大小。编译器可能会优化a / b 之类的表达式以在 8 位算术上执行,但只有在它可以推断出提升不会导致任何副作用时才能这样做。例如~(unsigned char)a / (unsigned char)b 必须使用有符号算术和左操作数作为负值执行 - 不允许编译器将其优化为无符号 8 位算术,因为这会改变代码的含义。
  • 我的业务时间太长,看到的事情太多,无法信任你,亲爱的 Lundin。如果你不确定不要相信。测试一下。避免不确定性。这是用 C 编写可靠代码的唯一方法。
  • 这听起来像是一个糟糕的借口,可以避免学习该语言的实际工作原理,而不是在你认为你做对之前随机和反复尝试错误。当然,C 既不合理也不简单,但该语言的所有缺陷现在都已广为人知。它不像 C++ 每 3 年引入数百个新危险。
  • 我在 windows 的 gcc 上测试过这个:signed char cx=-128, cy=-1;诠释 n = cx / cy;我得到了结果 n == +128;编译器所做的是“int n = (int)cx / (int)cy;”也许有一些规则,char 操作的结果在 C99 中是 int ? +128 不能用有符号字符表示。
猜你喜欢
  • 2016-11-13
  • 1970-01-01
  • 2011-04-16
  • 2017-06-02
  • 2014-07-08
  • 2014-05-13
  • 2017-12-27
  • 1970-01-01
  • 2011-10-31
相关资源
最近更新 更多