关于使用Arduino IDE 1.8.2 (gcc 4.9.2.)隐式转换uint8_t
和uint16_t
,我有一个问题。硬件是一个标准的Arduino (ATMega328p)。
我使用uint8_t
编写了一段代码,然后决定切换到uint16_t
。(应该预见到.)
但是,对于隐式转换,它们的行为似乎略有不同,这导致了程序中的错误。
下面是一个最低限度的工作示例:
void setup()
{
uint8_t x = 15;
uint8_t y = 5;
float myF = y-x;
Serial.begin(74880);
Serial.println(myF);
}
这将在我的串行控制台上打印-10点。
这很好,也是我所期望的。
但是,如果我将x
(或x
和y
)更改为uint16_t
,结果将是65526.00!如果我将myF
从浮点改为int,我将再次得到-10。(我从不改变任何一个值)
当我将结果存储在有符号的数据类型中时,我假设编译器意识到了负值的可能性,并“正确地处理情况”(保留符号,就像在int情况下那样),或者打印警告,以防它对数据类型不匹配感到高兴。但是,即使将警告级别设置为"all“,它也没有显示警告。因此,我假设编译器知道如何在不丢失符号/数据的情况下处理这种情况。
而且,由于它与int作为目标数据类型一起工作,所以它不适用于更大的浮点,这让我感到惊讶。
我已经测试了我的x86系统的情况- gcc 4.7.3保留了标志。然而,在AVR的8位微控制器世界中,可能适用不同的规则/条件。(?)
那到底是怎么回事?也许有更多编译知识的人能帮上忙。
(我知道我本可以通过明确的方式避免这种情况,但因此我必须意识到这个陷阱。
所以我想知道到底是什么原因造成的,因为从uint8_t
切换到uint16_t
真的是一个惊喜。)
我读过,根据整数转换规则,“当对整数执行操作时,小于int的整数类型被提升为int”。我想avr-gcc会跟随整型升迁。(?)因此,我理解实际的计算通常在int上运行,然后转换为目标数据类型(在本例中为float)。这里的问题是uint16_t
是相等的,但不是小于16位int的AVR,因此uint16_t
不能推广吗?如果是这样的话,为什么它使用一个int作为目标类型?
为什么它使用int作为目标变量,而不使用4字节浮点数呢?为什么不警告呢?
发布于 2018-06-13 18:53:03
那到底是怎么回事?
整数晋升
如果
int
可以表示原始类型的所有值.,则将该值转换为int
;否则,该值将转换为unsigned int
。这就是所谓的整数晋升。 C11§6.3.1.1 2
使用下面的代码,y-x
将每个x,y
提升到int
,并计算5-15,即int -10
,并将值分配给mF
。
uint8_t x = 15;
uint8_t y = 5;
float myF = y-x;
使用下面的代码,y-x
将每个x,y
提升到unsigned
,计算5u-15u,即unsigned 65526u
,并将值分配给mF
。
uint16_t x = 15;
uint16_t y = 5;
float myF = y-x;
为什么是unsigned
而不是int
?uint16_t
在提升uint16_t
时不满足16位int
平台上的“如果int
可以表示所有原始类型的值”的条件。
没有神秘,只有一个16位int/unsigned
平台上的整数促销。
https://stackoverflow.com/questions/50842339
复制相似问题