Reputation: 43
Could someone explain the logic behind this? Why void
? For example
#include <iostream>
using namespace std;
int main()
{
char c;
cout << (void *)&c;
return 0;
}
Upvotes: 4
Views: 590
Reputation: 238341
Why does
(void *)&
get the address of the variable?
The unary &
is the addressof operator. The addressof operator gets the address of the operand because that's the purpose of that operator.
Why void?
Because
The type of &c
is char*
, and pointers of that type are treated by the output stream as a pointer to a null terminated character string, which are handled differently from all other pointers. Specifically, the content of the string would be output. Inserting a char*
that isn't a pointer to a null terminated character string into a character stream would result in undefined behaviour. &c
is not a pointer to a null terminated character string. Inserting a pointer of another type into a character stream will instead result in the output of a numerical representation of the address.
The example converts &c
to another pointer type so that it won't be treated as a null terminated character string.
All object pointers can be converted to void*
, so that is the pointer type that is conventionally chosen for outputting the address of a character.
For a bit more detail, the character stream insert operator has overloads:
operator<<(ostrea&, const char*);
operator<<(ostrea&, const void*); // I'm cheating a bit
// this is technically a member overload
So would I need to convert it to void* when and only when a variable is NULL?
Not at all. The variable c
isn't null. And whether a pointer is null has no influence on whether or not it needs to be converted to void*
.
Also note that null terminator character - which terminates a null terminated string - is not a null pointer. And a null pointer is not a pointer to a null terminator character. Those are entirely different concepts.
Upvotes: 2
Reputation: 11340
cout << (void *)&c;
takes the address of c
, then casts it to void*
, then prints pointer.
The intent here is to print the address of variable c
. But when passing a char *
to std::cout <<
it will attempt to print a null-terminated string. To avoid this (and print the actual address) you have to cast to void*
first.
More explanation:
std::ostream::operator<<
has overload (2) that handles char *
and const char*
. It assumes that a const char*
will point to some string that is eventually terminated by a null-character '\0'
. That's simply a convention used in C and C++.
You want to avoid this and instead use overload (7) to print the address.
Upvotes: 6
Reputation: 310980
The operator <<
is overloaded for objects of the type char *
such a way that it outputs characters as if the used pointer is a pointer to the first character of a C-string (a sequence of characters terminated by the zero character '\0'
).
And the expression &c
without casting has the type char *
. So the operator assumes that the passed pointer expression &c
supplies a pointer to a C-string.
To output the address of the object c
you need to cast the expression &c
to the type void *
.
Here is a simple program that demonstrates the difference.
#include <iostream>
int main()
{
const char *s = "Hello";
std::cout << s << '\n';
std::cout << static_cast<const void *>( s ) << '\n';
return 0;
}
The program output is
Hello
0x5598fd4a3004
Upvotes: 4