我懂得在C语言中类型转换的高级含义。我知道有时候这是隐式完成,而有时候必须显式完成。但是我不清楚这是如何在低级别上实现的:
假设GetSignal
返回一个枚举类型
。
uint8 outValue;
f32_t iValue;
iValue = (f32_t)GetSignal();
outValue = (uint8)((i32_t)iValue);
我的问题是这里发生了什么。在进行所有的类型转换之后,我不知道位是如何被重新组织的。
cast的作用是将一个类型的值转换为另一个类型的值。 对于每种给定类型,该值的表示取决于类型。
假设GetSignal
返回一个枚举,其基础值为1。 作为32位整数,它的表示形式如下(假设采用大端字节顺序,即从高到低):
00000000 00000000 00000000 00000001
这个整数值1随后通过显式强制类型转换转换为f32_t
。假设该类型被表示为IEEE 754单精度浮点值,则其表示形式(从高到低)如下:
00111111 10000000 00000000 00000000
这个表示法被存储在 iValue
中。
然后将 iValue
强制转换为 i32_t
。因此,具有上述 IEEE754 浮点表示的 float
值 1 被转换为带有该表示的 int
值 1:
00000000 00000000 00000000 00000001
这与GetSignal
返回的结果相同。然后将该值转换为类型uint8
,其表示如下:
00000001
这个表示被存储在outValue
中。
关于你对于添加一个float
和一个int
的评论,通常算术转换规则指定类型为int
的值首先会隐式转换为float
类型,然后两个float
值可以相加,结果的类型为float
。
(uint8)(i32_t)a_float
- 如果将浮点数转换为整型时,其值不适合整型,则是未定义的行为;先转换为int32_t,然后再截断为uint8_t是明确定义的。在C标准中,将负double强制转换为unsigned int的行为是否已定义?在ARM和x86上的行为不同 - 这也适用于大于255的浮点数,这些浮点数也不适合uint8_t。因此,如果您有一个浮点数并想要将其整数部分截断为较窄的类型,请先将其转换为足够宽的整数类型。 - Peter Cordes
float
和int
相加时,该怎么办呢?它们都按照各自的标准在其寄存器中排序,如果ALU试图像对2个整数求和一样对它们求和,那么它将返回一个奇怪的结果。因此,我最好的猜测是进行了一些位操作。 - Ricardo Mostalacf32_t
是什么别名,就很难具体说明。名称(以及函数的名称)表明它是单精度float
而不是您所说的enum
。这对于强制转换的结果有重大影响。请勿使用我们必须猜测的typedef
别名来混淆问题-请使用标准库类型别名的实际数据类型。 - Clifford