printf() 混淆 - 尝试打印字符串时打印(null),并在打印缓冲区时打印正确的值

Pie*_*son 1 c++ string null printf

查看简化的代码 - 我很困惑......

#include <stdio.h>
#include <string>      
#include <cstdlib>  // includes the standard library and overarchs over stdlib.h

using namespace std;  
void main()
{
    char buffer[10];
    string theString;
    int i = 997799; //(simplified)
    itoa(i,buffer,10);                      
    theString = buffer;             

    printf("\n string is: %s of length %d \n", theString, theString.length());
    printf("\n buffer is: %s of length %d \n", buffer, theString.length());
    return;
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出是出乎意料的:

string is: (null) of length 926366009
buffer is: 997799 of length 6
Run Code Online (Sandbox Code Playgroud)

(1)为什么字符串打印为null?

(2) 为什么 theString.length() 在第一个 printf() 中打印不正确,但在第二个 printf() 中打印正确?

(3) 如果我在 Visual Studio 中设置断点,“buffer”显示为“997799”,而“theString”显示为 {“997799”} - 这里发生了奇怪的事情吗?

谢谢各位! 编辑我非常感谢所提供答案的详细程度 - 它们都增加了清晰度并帮助我超越了我的问题 - 非常感谢您花时间提供帮助:)

Die*_*ühl 5

当您使用%s说明符 with时printf(),您承诺传递 achar const*作为相应的参数。传递除 a 之外的任何内容char const*或衰减为 a 的内容char const*都是未定义的行为。当然,传递 C++ 对象会有未定义的行为。

std::string传递a的正确方法printf()是使用%s格式说明符并使用c_str()成员,例如:

printf("string=%s\n", s.c_str());
Run Code Online (Sandbox Code Playgroud)

您正在用作 的%d格式说明符std::string::size_type。这可能会起作用,但不能保证一定会起作用!虽然std::string::size_type保证是std::size_t,但这个类型可能是unsigned int、、、甚至是一些非标准的内置整型unsigned longunsigned long long拼写格式说明符的正确方法std::size_t%zu(当然不是%ul像另一篇文章中那样:它可能是%lu这样的,但是,仍然是错误的:

printf("string.size()=%zu\n", s.size());
Run Code Online (Sandbox Code Playgroud)

由于您使用的是 C++,因此最好让编译器确定要调用的格式:

std::cout << "\n string is: " << theString << " of length " << theString.length() << " \n";
std::cout << "\n buffer is: " << buffer << " of length " << theString.length() << " \n";
Run Code Online (Sandbox Code Playgroud)