我理解类型转换...但只是回想起来。我需要弄清楚需要在表达式中进行类型转换的过程通常是追溯性的,因为我无法预测何时需要它,因为我不知道编译器如何逐步执行它们。一个有点陈腐的例子:
int8_t x = -50;
uint16_t y = 50;
int32_t z = x * y;
在我的8位处理器(Freescale HCS08)上将z
设置为63036(2 ^ 16 - 50 ^ 2)。我可以看到这可能是一个可能的答案(可能有4个其他答案),但我不会猜到它会是那个。
更好的方式可能是:当类型与运算符(+-*/
)交互时,会发生什么?
答案 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
的所有类型都会提升为signed
或unsigned
,此处为unsigned
,因为您的某个类型是无符号类型。
然后使用该宽度和符号执行计算,最后分配结果。
在您的架构上unsigned
可能是16位宽,这与您看到的值相对应。然后,对于赋值,计算值适合更宽的目标类型,因此值保持不变。
答案 6 :(得分:0)
为了解释你的例子中发生了什么,你有一个带符号的8位类型乘以无符号16位类型,因此较小的有符号类型被提升为更大的无符号类型。创建此值后,将其分配给32位类型。
如果你只是使用有符号或无符号整数类型,那很简单。系统总是可以将较小的整数类型转换为较大的整数而不会损失精度,因此它会将较小的值转换为较大的类型。在混合浮点和整数计算中,它会将整数转换为浮点类型,可能会失去一些精度。
通过混合有符号和无符号类型,您似乎感到困惑。系统将转换为更大的类型。如果该较大类型已签名,并且可以在操作中保存无符号类型的所有值,则操作将以signed形式完成,否则为unsigned。通常,系统更喜欢将混合模式解释为无符号。
这可能是造成混淆的原因(例如,它使你感到困惑),这就是为什么我不完全喜欢C中无符号类型和算术的原因。我建议在实际操作中坚持使用签名类型,而不是尝试控制类型大小,就像你正在做的那样。