Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are the outputs of printf and std::cout different?

Tags:

c++

I tried the following code of C++. However, the outputs of printf and std::cout are different. Why?

struct Foo {     int a;     int b;     int c; };  int main() {     printf("%d\n", &Foo::c);  // The output is 8     std::cout << &Foo::c << "\n"; // The output is 1 } 
like image 378
uu dd Avatar asked Mar 14 '19 11:03

uu dd


People also ask

What is the difference between std :: cout and printf?

std::cout handles all types for you, while printf requires specific syntax depending on an integer type (there are non-integer types, but the only non-integer type you will use in practice with printf is const char * (C string, can be obtained using to_c method of std::string )).

Is std :: cout faster than printf?

To answer your question, printf is faster.

What is the difference between std :: cout?

std:cout: A namespace is a declarative region inside which something is defined. So, in that case, cout is defined in the std namespace. Thus, std::cout states that is cout defined in the std namespace otherwise to use the definition of cout which is defined in std namespace.

Can I use printf instead of cout in C++?

Cout in C++ The C++ printf() function is usually used in C programming but can also run in C++. However, the cout is specifically an addition in C++.


2 Answers

printf("%d\n", &Foo::c): this is undefined behavior, as &Foo::c is not an integer, but a pointer to member (but, actually, it is usual that the compiler stores pointer to data member as offset, and as 8 is the offset of Foo::c, 8 is printed).

std::cout << &Foo::c: this prints the value &Foo::c. As iostream doesn't have a pointer to member printer, it chooses the closest one: it converts it to bool, and prints it as integer. As &Foo::c converted to bool is true, 1 is printed.

like image 177
geza Avatar answered Oct 02 '22 15:10

geza


The output is different because the behavior of your printf is undefined.

A pointer to member (like the one produced from &Foo::c) is not an integer. The printf function expects an integer, since you told it too with the %d specifier.

You can amend it by adding a cast to bool, like this:

printf("%d\n", (bool)&Foo::c) 

A pointer to member may be converted to a bool (which you do with the cast), and the bool then undergoes integral promotion to an int on account of being an integral variadic argument to a variadic function.

Speaking of the conversion to bool, it's exactly the conversion that is applied implicitly by attempting to call std::ostream's operator<<. Since there isn't an overload of the operator that supports pointers to members, overload resolution selects another that is callable after implicitly converting &Foo::c to a boolean.

like image 35
StoryTeller - Unslander Monica Avatar answered Oct 02 '22 14:10

StoryTeller - Unslander Monica