将(void*)转换为std::vector<unsigned char>

17

我有一个 (void*) 缓冲区需要转换为 std::vector<unsigned char>,然后才能传递它。不幸的是,我的 C++ 强制类型转换技巧有点薄弱。有什么建议吗?

4个回答

28
您需要缓冲区的长度。一旦您拥有了它,我们就可以这样做:
unsigned char *charBuf = (unsigned char*)voidBuf;
/* create a vector by copying out the contents of charBuf */
std::vector<unsigned char> v(charBuf, charBuf + len);

好的,这个评论让我开始思考为什么我没有使用reinterpret_cast

  • 在C++中,C风格的转换是一种方便的函数——它要求编译器从可用的转换运算符集合中选择最安全和最便携的转换形式。

  • reinterpret_cast是实现定义的,应该始终是最后考虑的事情(并且在你有意进行不可移植操作时使用)。

  • unsigned转换到和之间的转换是可移植的(如果你非常挑剔,实际上可以使用static_cast)。

C风格的转换存在问题:当指针类型更改时,其添加的灵活性可能会导致困难。

注意:我同意尽可能避免进行强制类型转换的一般约定。然而,没有提供任何源代码,这就是我能做的最好的。


reinterpret_cast 更容易进行 grep 操作。 - Thomas L Holaday
@dirkgently:+1,但请指出这将创建缓冲区的副本——这很重要,但从您的帖子中并不明显。 - j_random_hacker
@j_random_hacker:OP提到了“传递”——我假设他的意思是复制。无论如何,我已经在源代码中更新了注释。 - dirkgently
我会查看C++03的修订内容。在C++98中我找不到任何允许它的东西。但如果我找到了,我会告诉你的。干杯 :) - Johannes Schaub - litb
@litb:我是指查阅C++0x草案。会继续关注的。 - dirkgently
显示剩余4条评论

3

你不能简单地将 void* 强制转换为 std::vector<unsigned char>,因为后者的内存布局包括其他对象,比如大小和当前分配的字节数。

假设缓冲区由 buf 指向且其长度为 n

vector<unsigned char> vuc(static_cast<char*>(buf), static_cast<char*>(buf) + n);

会创建一个缓冲区的副本,您可以安全地使用。

[编辑:添加了static_cast<char*>,需要用于指针算术运算。]


3
唯一合理的情况是您已经创建了一个向量,并且只想要将其取回。
void SomeFunc(void* input);

main() {
  std::vector< unsigned char > v;
  SomeFunc((void*) &v);
}

SomeFunc(void* input) {
  // Now, you could cast that void* into a vector
  std::vector< unsigned char >* v_ = (vector<unsigned char>*)input
}

我实际上没有尝试过看这是否可以运行,但这就是它的精神。话虽如此,如果你从头开始制作这个,那么你肯定是错的。这真的很糟糕。唯一能够稍微理解的情况是,如果你被迫实现已经定义好的"SomeFunc()"。


2
使用std::vector类来管理已分配的缓冲区并不是一个解决方案。std::vector对象管理内存,并在销毁时释放它。
一个复杂的解决方案可能是编写自己的分配器,使用已分配的缓冲区,但您必须非常小心处理多种情况,如向量调整大小等。
如果您通过某些C API函数绑定了该void*缓冲区,则可以忽略转换为std::vector。
如果您只需要该缓冲区的副本,则可以这样做:
std::vector< unsigned char> cpy( 
    (unsigned char*)buffer, (unsigned char*)buffer + bufferSize);

bufferSize是复制缓冲区的字符大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接