很好地定义了C ++将std :: vector传递给期望输出数组的C API,因为std :: vector是连续的:
std::vector<char> myArray(arraySize);
cStyleAPI(&myArray[0], arraySize);
以相同的方式将std :: string传递给C API是否安全?在标准C ++ 03中是否有任何保证std :: string是连续的并且在这种情况下与std :: vector的工作方式相同?
答案 0 :(得分:10)
如果C API函数要求对std::string
的内容进行只读访问,则使用std::string::c_str()
成员函数传递字符串。这保证是一个以空字符结尾的字符串。
如果您打算使用std::string
作为 out 参数,C ++ 03不保证存储的字符串在内存中是连续的,但C ++ 11可以。使用后者,只要您don't modify the terminating NULL character,就可以通过operator[]
修改字符串。
答案 1 :(得分:5)
所以,我知道这已经得到了解答,但我在Praetorian的回答中看到了你的评论:
嗯...原谅我,但如果这个是你的问题,那么所有这些解决方案似乎都过于复杂了。如果问题归结为你得到一个0作为你需要的缓冲区大小这一事实(这意味着你将得到一个非NULL终止的字符串,因为没有空间用于NULL终止符)然后只需确保NULL终止符始终存在:这是一个OpenGL驱动程序错误,导致返回值 最大长度字符串被破坏。看到 https://forums.geforce.com/default/topic/531732/glgetactiveattrib-invalid/。 glGetActiveAttrib不会尝试写入由返回的指针 new []调用0大小分配,但字符串不为null 终止。然后,在代码的后面,非空终止字符串是 复制到std :: string进行存储,从而产生读缓冲区 溢出。我也很困惑,只是在这里查看是否 std :: string会让事情变得更容易理解。
int arraySize;
/* assume arraySize is set to the length we need */
...
/* overallocate by 1 to add an explicit NULL terminator. Just in case. */
char *ptr = malloc(arraySize + 1);
if(ptr != NULL)
{
/* zero out the chunk of memory we got */
memset(ptr, 0, arraySize + 1);
/* call OpenGL function */
cStyleAPI(ptr, arraySize);
/* behold, even if arraySize is 0 because of OpenGL, ptr is still NULL-terminated */
assert(ptr[arraySize] == 0);
/* use it */
...
/* lose it */
free(ptr);
}
对我来说,这似乎是最简单,最安全的解决方案。
答案 2 :(得分:1)
是的,但您需要使用c_str方法传递它们以保证空终止。
答案 3 :(得分:0)
不,它不是,但通常是因为C字符串被假定为零终止,而指针指向char
则不是。 (如果您使用string
,则可以使用string::c_str()
代替,即0终止。)
无论如何,C ++ 11确实要求vector
的元素在内存中是连续的。
答案 4 :(得分:0)
cStyleAPI(&myArray[0], arraySize);
如果cStyleAPI
收到char *作为输入,那就是std::string::c_str()
的用途。
如果收到预先分配的char *用于输出,则否。在这种情况下,您应该使用std::vector<char>
或std::array<char>
。