c++ - 当数据存储为 uint8_t 的向量时,如何传递“char* 数据”?
问题描述
我有一个这样定义的类:
class sco
{
private:
public:
vector<uint8_t> data;
sco(vector<uint8_t> data);
~sco();
};
构造函数在哪里:
sco::sco(vector<uint8_t> data) {
this->data = data;
}
然后我有一个这样声明的函数:
void send(unsigned& id, char* data, char len);
我的问题是我需要将 sco 成员的数据传递给它,但是类型和指针的差异让我感到困惑。如果我有一个包含一些数据的成员 newSco,将这个发送函数称为 是否合理send(someId, (char*)&(newSco.data.begin()), newSco.data.size() );
?请注意,函数 send 是针对微控制器的,它采用 char 类型,所以我不能改变它,我也不能改变 uint8_t 因为它是来自串行通信的类型。我浪费了 3 天多的时间试图将类型转换为相互的东西,只是为了将其反转回来,因为它破坏了一切。我放弃了,我将不再尝试操纵类型,因为我没有那种时间,即使这是不好的做法,我也需要它来工作。我认为 uint8_t 和 char 大小相同,所以没关系。
解决方案
send(someId, (char*)&(newSco.data.begin()), newSco.data.size() )
你几乎拥有它,但不完全是。
原因如下:
begin()
给你一个迭代器。您正在获取该迭代器的地址,因此您是间接级别。使用 C 风格的强制转换掩盖了与类型相关的编译错误。我们可以
(char*)&*(newSco.data.begin())
改为取消引用迭代器,然后获取结果第一个元素的地址。但是如果容器是空的,那就很破了。你不能取消引用一个不存在的东西。
所以现在我们尝试:
send(someId, (char*)&newSco.data[0], newSco.data.size() )
不幸的是,如果容器为空,这也是不安全的,因为.data[0]
还会有效地取消引用可能不存在的元素。有人认为暗示的&*
“取消它”,但这是有争议的,我从不相信。
如果你曾经迁移到 C++11 或更高版本,你可以使用完全安全的:
send(someId, (char*)newSco.data.data(), newSco.data.size() )
否则,坚持&newSco.data[0]
但跳过整个send
呼叫当newSco.data.size()
是零。怎么强调都不过分。
转换char*
为本身是安全的;你可以用这种方式自由地将 s 解释uint8_t
为char
s;有一个特殊的规则。我自己使用过这种模式几次。
但是,如上所述,C 风格的演员表并不理想。更喜欢一个好的重新解释。我还会添加一些const
好的措施(如果您的 MC 的 API 不允许,请跳过此步骤):
if (!newSco.data.empty())
{
send(
someId,
reinterpret_cast<const char*>(&newSco.data[0]),
newSco.data.size()
);
}
那里。华丽的。
最后一点,由于 API 将 achar
作为最终参数,我会考虑为容器大小设置一个上限。您可以在循环中运行该函数,一次发送一个CHAR_MAX
或多个newSco.data.size()
字节(以较小者为准)。否则,如果您期望容器中的元素不止CHAR_MAX
一个,您将得到一个令人讨厌的溢出!
推荐阅读
- java - 可以用于 HTML5 标签的 IntelliJ JavaDoc 检查器吗?
- javascript - 如何将php变量值输入到javascript中
- project-reactor - 如何将 Mono 转换为 Mono
万一出错 - selenium - 如何在先前的兄弟姐妹中导航
- javascript - 获取所选单词的正确索引 - Javascript
- angular - Angular Json 数据在组件 html 中显示
- asp.net - 超出最大请求长度
- c# - IActionResult 与 OkObjectResult 有什么区别?
- docker - 如何自动将版本为标签的 docker php 图像标记为最新?
- vim - prevblank() 或 startpara() 函数?