我的理解是,字符串是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++扩展中,那就太好了。

其他回答

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());

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.

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

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

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

请不要使用printf("%s", your_string.c_str());

使用cout << your_string;代替。简短,简单,类型安全。事实上,当您在编写c++时,您通常希望完全避免printf——它是C的遗留物,在c++中很少需要或有用。

至于为什么应该使用cout而不是printf,原因有很多。以下是一些最明显的例子:

As the question shows, printf isn't type-safe. If the type you pass differs from that given in the conversion specifier, printf will try to use whatever it finds on the stack as if it were the specified type, giving undefined behavior. Some compilers can warn about this under some circumstances, but some compilers can't/won't at all, and none can under all circumstances. printf isn't extensible. You can only pass primitive types to it. The set of conversion specifiers it understands is hard-coded in its implementation, and there's no way for you to add more/others. Most well-written C++ should use these types primarily to implement types oriented toward the problem being solved. It makes decent formatting much more difficult. For an obvious example, when you're printing numbers for people to read, you typically want to insert thousands separators every few digits. The exact number of digits and the characters used as separators varies, but cout has that covered as well. For example: std::locale loc(""); std::cout.imbue(loc); std::cout << 123456.78; The nameless locale (the "") picks a locale based on the user's configuration. Therefore, on my machine (configured for US English) this prints out as 123,456.78. For somebody who has their computer configured for (say) Germany, it would print out something like 123.456,78. For somebody with it configured for India, it would print out as 1,23,456.78 (and of course there are many others). With printf I get exactly one result: 123456.78. It is consistent, but it's consistently wrong for everybody everywhere. Essentially the only way to work around it is to do the formatting separately, then pass the result as a string to printf, because printf itself simply will not do the job correctly. Although they're quite compact, printf format strings can be quite unreadable. Even among C programmers who use printf virtually every day, I'd guess at least 99% would need to look things up to be sure what the # in %#x means, and how that differs from what the # in %#f means (and yes, they mean entirely different things).