0

I was reading this. That question contains following program.

#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;
}

I tried it on g++ 4.8.1 & it fails in compilation. g++ 4.8.1 gives following diagnosis.

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=]

What does this error mean? Should this program compile successfully or not? Which compiler is correct (g++ or MSVS 2010) ? Why MSVS 2010 accepts this code? Is the code invokes undefined behavior when compiled on MSVS 2010?

Surprising: I tried it on ideone which uses g++ 5.0 & surprisingly it compiles & runs fine. (See live demo here.). g++ 5.2.0 gives warning when I compile this code. (See live demo here). Why it compiles fine on ideone but fails on g++ 4.8.1? g++ 4.8.2(gives same diagnosis as g++ 4.8.1, 4.9.0,4.9.1,4.9.2 (gives error not warning). g++ 5.1.0 gives warning but program still compiles & runs fine.

Why different versions of g++ behave differently when compiling above program? Is this bug in g++ ? Clang also rejects this code to compile in response to answer given by @TemplateRex

Community
  • 1
  • 1
Destructor
  • 14,123
  • 11
  • 61
  • 126

1 Answers1

1

Clang errors out with "error: cannot pass non-trivial object of type 'string' (aka 'basic_string') to variadic function; expected type from format string was 'char *' [-Wnon-pod-varargs]" and suggests the fix "note: did you mean to call the c_str() method?"

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

and it seems to work.

Destructor
  • 14,123
  • 11
  • 61
  • 126
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • If you remove call to c_str() function then it will fail in compilation & gives exactly same errors given by g++ 4.8.1, 4.8.2 , 4.9.0, 4.9.1 & 4.9.2 – Destructor Sep 17 '15 at 07:06
  • 1
    @PravasiMeet `printf` is not suited for `std::string`, just paste the `c_str()` to it and you're in business – TemplateRex Sep 17 '15 at 07:07
  • Yes right. but question is why different compilers react differently when compiling this program? – Destructor Sep 17 '15 at 07:08
  • 1
    @PravasiMeet in the [Q&A](http://stackoverflow.com/a/10865967/819272) given in the comments to your OP, it is pointed out that passing `std::string` to `printf` is undefined behavior. Anything can happend in that case, including successfull compilation and output. But you shouldn't rely on that. – TemplateRex Sep 17 '15 at 07:10
  • 1
    @PravasiMeet - It is **your** responsibilty to match up the format string with the parameters. Some compilers might be nice and tell you when you fail that, but they don't have to. With some calling conventions, and on implementations where `std::string` happens to have a pointer as its first member, `printf` might *believe* it gets a C style string and display it correctly *by accident*. – Bo Persson Sep 17 '15 at 07:20