我什么时候需要在C中进行类型转换?

时间:2010-09-17 17:02:28

标签: c embedded casting

我理解类型转换...但只是回想起来。我需要弄清楚需要在表达式中进行类型转换的过程通常是追溯性的,因为我无法预测何时需要它,因为我不知道编译器如何逐步执行它们。一个有点陈腐的例子:

int8_t x = -50;
uint16_t y = 50;
int32_t z = x * y;

在我的8位处理器(Freescale HCS08)上将z设置为63036(2 ^ 16 - 50 ^ 2)。我可以看到这可能是一个可能的答案(可能有4个其他答案),但我不会猜到它会是那个。

更好的方式可能是:当类型与运算符(+-*/)交互时,会发生什么?

7 个答案:

答案 0 :(得分:3)

将编译器转发为表达式中的最大类型,然后将结果放入该位置的大小。如果您要查看上面的汇编器输出,您可以确切地看到如何从内存中以本机格式读取类型。从较小尺寸到较大尺寸的向上安装是安全的,不会产生警告。当你从较大的类型转变为较小的类型时,精度可能会丢失并且编译器应该发出警告或错误。

有些情况下,您希望信息丢失。假设您正在使用长度为256个条目的sin / cos查找表。使用u8值访问表格是非常方便和常见的(至少在嵌入式土地中),以便索引自然地包裹在表格大小中,同时预先确定sin / cos的循环性质。然后需要将类型转换回u8,但这正是你想要的。

答案 1 :(得分:2)

这里的人说,值总是转换为更大的类型是错误的。如果我们不了解您的平台,我们就无法谈论任何事情(我看到您现在提供了一些信息)。一些例子

  

int = 32bits,uint16_t = unsigned short,int8_t = signed char

这导致值-2500,因为两个操作数都转换为int,操作执行签名,签名结果写入int32_t

  

int = 16bits,uint16_t = unsigned int,int8_t = signed char

这会产生值63036,因为int8_t操作数首先转换为unsinged int,从而产生65536-50。然后将它与它相乘,得到3 274 300 % 65536(无符号为模运算),即63036.然后将该结果写入int32_t

请注意,最小int位大小为16位。因此,在您的8位平台上,第二种情况可能发生。


我不打算尝试解释这里的规则,因为对于我来说,重复标准/草稿(免费提供)中的内容非常有意义并且通常很容易理解。

答案 2 :(得分:1)

你在向下投射时需要进行类型转换。

upcasting是自动的并且是安全的,这就是编译器永远不会发出警告/错误的原因。但是当你进行向下转换时,你实际上放置的值的精度高于你存储它的变量的类型,这就是为什么编译器要你确定并且你需要明确地向下转换。

答案 3 :(得分:1)

当编译器执行隐式转换时,它遵循一组标准的算术转换。这些内容记录在第6.3节的the C standard中。如果您碰巧拥有the K&R book,则附录A6.5中有一个很好的摘要。

答案 4 :(得分:1)

如果您想要一个完整的答案,请查看其他人的建议。阅读有关隐式类型转换的C标准。并为您的代码编写测试用例...

你说这个很有意思,因为这段代码:

#include "stdio.h"
#include "stdint.h"

int main(int argc, char* argv[])
{
  int8_t x = -50;
  uint16_t y = 50;
  int32_t z = x * y;
  printf("%i\n", z);
  return 0;
}

给我答案-2500

请参阅:http://codepad.org/JbSR3x4s

在Codepad.org和Visual Studio 2010上都会发生这种情况

答案 5 :(得分:1)

这里发生的是整数提升。基本上在计算发生之前,排名小于int的所有类型都会提升为signedunsigned,此处为unsigned,因为您的某个类型是无符号类型。 然后使用该宽度和符号执行计算,最后分配结果。

在您的架构上unsigned可能是16位宽,这与您看到的值相对应。然后,对于赋值,计算值适合更宽的目标类型,因此值保持不变。

答案 6 :(得分:0)

为了解释你的例子中发生了什么,你有一个带符号的8位类型乘以无符号16位类型,因此较小的有符号类型被提升为更大的无符号类型。创建此值后,将其分配给32位类型。

如果你只是使用有符号或无符号整数类型,那很简单。系统总是可以将较小的整数类型转换为较大的整数而不会损失精度,因此它会将较小的值转换为较大的类型。在混合浮点和整数计算中,它会将整数转换为浮点类型,可能会失去一些精度。

通过混合有符号和无符号类型,您似乎感到困惑。系统将转换为更大的类型。如果该较大类型已签名,并且可以在操作中保存无符号类型的所有值,则操作将以signed形式完成,否则为unsigned。通常,系统更喜欢将混合模式解释为无符号。

这可能是造成混淆的原因(例如,它使你感到困惑),这就是为什么我不完全喜欢C中无符号类型和算术的原因。我建议在实际操作中坚持使用签名类型,而不是尝试控制类型大小,就像你正在做的那样。