首页 > 解决方案 > 当数据存储为 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 大小相同,所以没关系。

标签: c++c++98mbed

解决方案


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_tchars;有一个特殊的规则。我自己使用过这种模式几次。

但是,如上所述,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一个,您将得到一个令人讨厌的溢出!


推荐阅读