在RHEL linux中,使用带有“”(空字符串值)的std :: string变量给出了垃圾值

时间:2014-11-04 15:06:10

标签: c++ linux

在RHEL linux中,使用带有""(空字符串值)的std :: string变量给出垃圾值

例如,如下面的代码

std::string str = "";

printf("%s",str.c_str());

我还有一个代码示例

int main()
{
string str = "";
printf("Str = %s\n" ,str.c_str());

string strTemp;
char * pcTRMP = new char [10];

//sprintf(pcTRMP,"%d" ,7);
sprintf((char*)strTemp.c_str() ,"%d" ,7);
printf("Str = %s\n" ,str.c_str());

sprintf((char*)strTemp.c_str() ,"%d" ,8);
printf("Str = %s\n" ,str.c_str());

return 0;
}

结果是 Str = 7 Str = 8

没有赋值给str变量。

我们在互联网上查了很多地方。 我希望有人可以帮我解决这个问题。

相同的代码适用于旧版本的RHEL Linux。

2 个答案:

答案 0 :(得分:2)

写入std::string::c_str()返回的指针是违法的。 documentation for std::string明确表示这会导致未定义的行为。此指针最初为const char *类型,专门用于表示此限制。

关于程序显示的结果,我猜两个字符串都指向相同的空字符串缓冲区(一些内部const char empty[] = ""),因此写入一个会导致更改所有空字符串的值。

如果您确实需要使用sprintf而不是std::stringstream,则可以使用字符向量而不是字符串:

std::vector<char> buf(10);
sprintf(buf.data(), "%d" ,7);
std::string result = buf.data();

答案 1 :(得分:0)

你正在搞乱内部字符串指针,结果遇到了未定义的行为。

std :: string对象是C ++字符串对象。你创建这样一个对象(str),然后创建第二个(strTemp),从第二个获取一个const char * - 然后你尝试将整数写入该char数组。当然,编译器知道这是错误的(const)并会抱怨:

  

从const char *到char *

的无效转换

所以你通过强制转换const来强行忽略这个错误。 现在,在强行忽略错误之后,意外的事情发生了。

这与平台无关,至少在一般情况下如此。由于它是未定义的行为,因此症状可能因您使用的平台而异。我认为两个字符串对象(都是空的)共享相同的内存位置(至少只要它们相同)(在使用的平台上),所以覆盖第二个字符串返回的指针后面的内存也会影响第一个字符串对象。如果为字符串分配不同的值,the sprintf() won't (depending on platform) affect the other string anymore (example) - 当然这仍然是错误的。

阅读C ++ / C(C ++对象,C指针和const的含义),特别是documentation of std::string

修改

操作似乎专注于平台,因此我将在此处重复这一点。写入(const表示)变量a(strTemp)然后期望数据在变量b(str)中是假的。您正在覆盖您不拥有的内存,并且巧合地覆盖另一个变量(str)的内部内存。在某些情况下,该数据恰好最终会出现在另一个变量中。这完全被彻底打破了 我真的希望这只是一个测试程序或其他东西 - 而不是一个高效的应用程序。

不要像那样混合使用C / C ++。在C ++中,你仍然可以创建一个char *(足够大)并使用像sprintf()这样的函数来期望这样的C字符串写入它 - 如果有充分的理由的话。否则,只需编写适当的C ++。

例如,如果将int转换为C ++字符串是您的实际问题,这是一个示例:

#include <iostream>
#include <sstream>

//...
std::string str;
int number = 7;
ostringstream oss;
oss << number;
str = oss.str();

有些人为此写了macros。还有其他解决方案(我认为boost有提供的东西,C ++ 0x也是如此)。