我的理解是,字符串是std名称空间的成员,那么为什么会发生以下情况?

#include <iostream>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString);
    cin.get();

    return 0;
}

每次程序运行时,myString输出一个看似随机的3个字符的字符串,如上面的输出。


当前回答

主要原因可能是c++字符串是一个包含当前长度值的结构体,而不仅仅是以0字节结束的字符序列的地址。Printf及其相关函数希望找到这样的序列,而不是结构体,因此会被c++字符串弄糊涂。

就我个人而言,我相信printf有一个c++语法特性无法轻易填充的地方,就像html中的表结构有一个div无法轻易填充的地方一样。就像Dykstra后来写的goto一样,他并不打算开始一种宗教,实际上只是反对把它作为一个拼凑品来弥补设计糟糕的代码。

如果GNU项目能将printf家族添加到他们的g++扩展中,那就太好了。

其他回答

您可以使用snprinft来确定所需的字符数量,并分配适当大小的缓冲区。

int length = std::snprintf(nullptr, 0, "There can only be %i\n", 1 );
char* str = new char[length+1]; // one more character for null terminator
std::snprintf( str, length + 1, "There can only be %i\n", 1 );
std::string cppstr( str );
delete[] str;

这是对cppreference.com上一个例子的一个小的改编

printf accepts a variable number of arguments. Those can only have Plain Old Data (POD) types. Code that passes anything other than POD to printf only compiles because the compiler assumes you got your format right. %s means that the respective argument is supposed to be a pointer to a char. In your case it is an std::string not const char*. printf does not know it because the argument type goes lost and is supposed to be restored from the format parameter. When turning that std::string argument into const char* the resulting pointer will point to some irrelevant region of memory instead of your desired C string. For that reason your code prints out gibberish.

While printf is an excellent choice for printing out formatted text, (especially if you intend to have padding), it can be dangerous if you haven't enabled compiler warnings. Always enable warnings because then mistakes like this are easily avoidable. There is no reason to use the clumsy std::cout mechanism if the printf family can do the same task in a much faster and prettier way. Just make sure you have enabled all warnings (-Wall -Wextra) and you will be good. In case you use your own custom printf implementation you should declare it with the __attribute__ mechanism that enables the compiler to check the format string against the parameters provided.

Printf is actually pretty good to use if size matters. Meaning if you are running a program where memory is an issue, then printf is actually a very good and under rater solution. Cout essentially shifts bits over to make room for the string, while printf just takes in some sort of parameters and prints it to the screen. If you were to compile a simple hello world program, printf would be able to compile it in less than 60, 000 bits as opposed to cout, it would take over 1 million bits to compile.

对于您的情况,我建议使用cout,因为它使用起来要方便得多。尽管我认为printf是值得了解的东西。

使用std::printf和c_str() 例子:

std::printf("Follow this command: %s", myString.c_str());

主要原因可能是c++字符串是一个包含当前长度值的结构体,而不仅仅是以0字节结束的字符序列的地址。Printf及其相关函数希望找到这样的序列,而不是结构体,因此会被c++字符串弄糊涂。

就我个人而言,我相信printf有一个c++语法特性无法轻易填充的地方,就像html中的表结构有一个div无法轻易填充的地方一样。就像Dykstra后来写的goto一样,他并不打算开始一种宗教,实际上只是反对把它作为一个拼凑品来弥补设计糟糕的代码。

如果GNU项目能将printf家族添加到他们的g++扩展中,那就太好了。