Implicit conversion to float using avr-gcc: uint8_t vs. uint16_t
我有一个关于使用Arduino IDE 1.8.2(gcc 4.9.2。)隐式转换
我使用
但是,它们对于隐式转换的行为似乎略有不同,这导致了程序错误。
最小的工作示例如下:
1 2 3 4 5 6 7 8 9 | void setup() { uint8_t x = 15; uint8_t y = 5; float myF = y-x; Serial.begin(74880); Serial.println(myF); } |
这将在我的串行控制台上打印-10.00。
很好,也是我所期望的。
但是,如果将
如果将
当我将结果存储为带符号的数据类型时,我假设编译器意识到了负值的可能性,并"正确处理了情况"(保留符号,与int情况一样),或者在警告不存在时打印警告。对于数据类型不匹配感到高兴。但是,即使将警告级别设置为"全部",也不会显示警告。因此,我假设编译器知道如何处理这种情况而不会丢失符号/数据。
另外,由于它可以将int作为目标数据类型使用,所以令我惊讶的是它不适用于较大的float。
我已经在x86系统上测试了这种情况-gcc 4.7.3保留了该标志。但是,在AVR的8位微控制器领域中,可能适用不同的规则/条件。 (?)
那到底是怎么回事?也许有更多编译器知识的人可以在这里提供帮助。
(我知道我可以通过显式强制转换来避免这种情况,但是因此,我不得不意识到这一陷阱。
因此,我想知道到底是什么原因造成的,因为从
我已经读过,根据整数转换规则,"对小于int的整数类型在对其执行操作时会提升为int"。我假设avr-gcc遵循整数促销。 (?)因此,我知道实际的计算通常无论如何都在int上运行,然后转换为目标数据类型(在这种情况下为float)。这里的问题是
为何将int作为目标变量而不使用4字节浮点数呢?
为什么不警告呢?
So what is going on there?
整数促销
If an
int can represent all values of the original type ..., the value is converted to anint ; otherwise, it is converted to anunsigned int . These are called the integer promotions.
C11 §6.3.1.1 2
对于以下内容,
1 2 3 | uint8_t x = 15; uint8_t y = 5; float myF = y-x; |
对于以下内容,
1 2 3 | uint16_t x = 15; uint16_t y = 5; float myF = y-x; |
为什么是
毫无疑问,在具有16位
您正在使用无符号整数去负数 del>,将这些无符号类型强制转换为浮点数,即实现定义的行为 undefined del>。 使用int8_t或int16_t正确处理负值。 从uint16_t浮动的转换与从uint8_t转换的转换在行为上的差异取决于实现,因此很难确切说明正在发生什么。