【问题标题】:Why this C++ program behave differently on different compilers? [duplicate]为什么这个 C++ 程序在不同的编译器上表现不同? [复制]
【发布时间】:2015-12-13 23:12:18
【问题描述】:

我正在阅读this。该问题包含以下程序。

#include <iostream>
#include <cstdio>
#include <string>
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;
}

我在 g++ 4.8.1 上尝试过,但编译失败。 g++ 4.8.1 给出以下诊断。

9 47 [Error] cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...' 
9 47 [Warning] format '%s' expects argument of type 'char*', but argument 2 has type 'std::string {aka std::basic_string<char>}' [-Wformat=]

这个错误是什么意思?该程序是否应该编译成功?哪个编译器是正确的(g++ 或 MSVS 2010)?为什么 MSVS 2010 接受此代码?代码在 MSVS 2010 上编译时会调用未定义的行为吗?

令人惊讶:我在使用 g++ 5.0 的 ideone 上进行了尝试,令人惊讶的是它编译和运行良好。 (见现场演示here.)。当我编译这段代码时,g++ 5.2.0 会发出警告。 (见现场演示here)。为什么它在 ideone 上编译得很好,但在 g++ 4.8.1 上却失败了? g++ 4.8.2(给出与 g++ 4.8.1、4.9.0、4.9.1、4.9.2 相同的诊断(给出错误而不是警告)。g++ 5.1.0 给出警告但程序仍然编译和运行良好。

为什么不同版本的 g++ 在编译上述程序时表现不同?这是 g++ 中的错误吗? Clang 也拒绝编译此代码以响应@TemplateRex 给出的答案

【问题讨论】:

  • 它真的运行良好吗?两个现场演示似乎都没有正确显示myString 的内容。
  • 它给出了错误,因为您正在做一些不允许的事情,即使用带有旧 C 函数的 C++ 对象,这根本不可能。
  • @JoachimPileborg:那么为什么它在 g++ 5.1.0、5.2.0 上编译成功而没有任何错误?
  • @StillLearning:这不是重复的。如果它是重复的,那么我在发布这个问题时不会链接那个问题。
  • 另见stackoverflow.com/questions/10083844/…,它专门解释了为什么不同版本的行为可能不同。

标签: c++ visual-studio-2010 c++11 g++ compiler-bug


【解决方案1】:

Clang 错误提示“错误:无法将'string'(又名'basic_string')类型的非平凡对象传递给可变参数函数;格式字符串的预期类型是'char *' [-Wnon-pod-varargs]”并建议修复“注意:您的意思是调用 c_str() 方法吗?”

#include <iostream>
#include <cstdio>
#include <string>
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.c_str());
    cin.get();
}

seems to work

【讨论】:

  • 如果您删除对 c_str() 函数的调用,那么它将在编译中失败并给出 g++ 4.8.1、4.8.2、4.9.0、4.9.1 和 4.9.2 给出的完全相同的错误
  • @PravasiMeet printf 不适合std::string,只需将c_str() 粘贴到它上面就可以了
  • 是的,没错。但问题是为什么不同的编译器在编译这个程序时会有不同的反应?
  • @PravasiMeet 在 cmets 中给您的 OP 的 Q&A 中指出,将 std::string 传递给 printf 是未定义的行为。在这种情况下,任何事情都可能发生,包括成功编译和输出。但你不应该依赖它。
  • @PravasiMeet - 将格式字符串与参数匹配是您的责任。一些编译器可能会很好,并在您失败时告诉您,但他们不必这样做。使用一些调用约定,并且在 std::string 恰好有一个指针作为其第一个成员的实现上,printf 可能相信它得到一个 C 样式字符串并正确显示它偶然.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 2013-05-16
  • 2021-11-22
  • 1970-01-01
相关资源
最近更新 更多