【发布时间】:2014-05-01 19:39:19
【问题描述】:
我想将浮点数等大型变量拆分为字节段,并通过 UART 逐字节串行发送。我正在使用 C/C++。
一种方法是深度复制我想要发送到联合的值,然后发送它。我认为这将是 100% 安全但缓慢。工会看起来像这样:
union mySendUnion
{
mySendType sendVal;
char[sizeof(mySendType)] sendArray;
}
另一种选择是将指向我要发送的值的指针转换为指向特定联合的指针。这还安全吗?
第三个选项可能是将指针转换为我要发送到字符的值,然后像这样增加一个指针:
sendType myValue = 443.2;
char* sendChar = (char*)myValue;
for(char i=0; i< sizeof(sendType) ; i++)
{
Serial.write(*(sendChar+j), 1);
}
上面的指针算法我已经成功了,但我不确定它在所有情况下是否安全。我担心的是,如果我们使用 32 位处理器并想要发送浮点数怎么办。编译器选择将这个 32 位浮点数存储到一个内存单元中,但在每个 32 位单元中只存储一个字符。
然后,每个计数器增量都会使程序指针增加一个完整的内存单元,我们会错过浮点数。
C 标准中有什么东西可以防止这种情况发生吗,或者这可能是某个编译器的问题?
【问题讨论】:
-
使用联合进行类型双关将导致 C++ 中的未定义行为,不应被视为安全。
-
这两种解决方案都不是安全的,都可能会失败。他们只是碰巧经常工作(大部分时间),人们一直在这样做......打字机更安全一些,因为它没有对齐问题
-
你认为联合为什么会慢?
-
确保考虑字节序;并非所有平台都以相同的顺序存储构成(例如)32 位浮点数的四个字节,因此您需要确保连接的两端在表示上达成一致。
-
@dwelch “类型转换更安全,因为它没有对齐问题”是什么意思?两种解决方案都是错误的(在 C++ 中,如果类型不同)或者两者都很好(在 C99 及更高版本中,当类型兼容或别名指针的引用类型为
[un]signed char)或仅基于联合的解决方案是好的(在 C 中,当类型不同但双关指针不是char *时)或者只有基于指针的解决方案是好的(在 C++ 中,当类型不兼容并且别名指针的引用类型是[un]signed char时) .
标签: c++ c arduino embedded unions