在Visual Studio中通过printf()打印std :: string

Ale*_*der 2 c++ std visual-c++ visual-studio-2012

#include <string>
#include <cstdio>
int main() {
  std::string s = "12345678";
  std::printf("[%s]\n", s);
}
Run Code Online (Sandbox Code Playgroud)

这是一个缺少".c_str()"的明显错字.但VS2011即使使用/ Wall也不会发出任何警告,并且程序正常运行.如果要在gcc中编译此代码,它会显示"警告:无法传递非POD类型的对象'struct std :: string'到'...';调用将在运行时中止"并且程序崩溃时出现"非法指令" .

他们真的在VS STL中实现了一个技巧,让程序有这样的拼写错误只是因为这个拼写错误很常见吗?

更新:问题是为什么它在VS中有效?

Jon*_*rdy 9

原因似乎是在Visual Studio的实现中std::string,第一个成员是char*.传递stringby值会将此指针(以及其他数据成员)复制到堆栈上,以及读取它的%s原因- 并正确解释它,因为需要以null结尾.printf()char*string

当然,这是依赖于未定义的行为,您不应该这样做.

  • @NeelBasu不,它不会尝试将它投射到任何东西.对于可变参数函数没有类型检查,实际的`printf`函数只是盲目地将字节解释为你告诉它的类型.它无法知道你实际发送了什么. (2认同)
  • @NeelBasu:诸如`printf()`之类的变量函数不是(一般来说)类型检查的.编译器尝试为潜在的格式字符串错误提供诊断,但标准并未强制要求.使用`va_arg()`读取错误类型的可变参数只是调用未定义的行为. (2认同)

Dav*_*nan 7

它的工作原理是因为未定义行为的一个可能结果是程序按照您的意图执行.你不需要再看这个了.未定义的行为是您可以避免的,而不是试图在一个特定的编译器中理解它的表现形式.