I thought I had a decent knowledge of pointers until I decided to review some so called trivial examples.
One thing I know is that when declaring an array say:
int arr[2] {3, 5};
arr
will hold the value of the first element in the array so attempting to print that ( cout << arr
) gives obviously the address of arr[0]
. Even thought my program uses pointers it's still similar.
My question is why can I print h
and have bonjour
as output, but I can't do the same with p
?
It also looks like when I increment h++
and print it again I get onjour
. How are pointers different with char
?
#include <iostream>
#include <string>
int main()
{
char* h = "bonjour";
int k[4]{3, 4, 5, 6};
int * p = k;
std::cout << "Hello, "<< h << "!\n";
}
When you stream h
, you are using this overload :
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
But when you stream p
, you are using this one :
basic_ostream& operator<<( const void* value );
The former will print every byte until it gets to a \\0
, the latter will simply print the address. That is - there's simply a special case for const char*
that you're taking advantage of.
why can i print
h
and havebonjour
as output and i can't do the same withp
? it also looks like when i incrementh++
and print it again i getonjour
. how are pointers different withchar
?
The standard library provides two overloads of the operator<<
function for dealing with pointers.
A member function overload:
basic_ostream& operator<<( const void* value );
and a non-member function overload:
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
The first one is invoked when cout << ptr
is used for all pointers that are not of type char*
or char const*
. The second is used for all pointers that are of tpe char*
or char const*
. The second one outputs everything up to the terminating null characters while the first one outputs just the pointer value.
That explains the output.
It's instructive to understand why the standard library treats them differently.
The language and the standard libraries make exceptions to the null terminated strings that are represented by char*
and char const*
. When dealing with strings, the null character ( '\\0'
) acts as a sentinel value that marks the end of the string. There is no such value for other types. Hence, an int*
cannot be treated the same was a char*
.
char*
can be special in some circumstances, because C decided to use it for representing strings. In that case a char*
refers to a null terminated array of characters, aka C-string. The reason you can print h
but not p
is because there exists a function that does the special handling for char*
:
std::ostream::operator<<(std::ostream& os, const char*);
You could provide your own overload to print null terminated integer arrays:
std::ostream& operator<<(std::ostream& os, const int* arr) {
while (int i = *arr++) {
os << i;
if (*arr) os << ", ";
}
return os;
}
int main()
{
const int arr[] = {1, 2 ,3, 4, 0};
std::cout << arr << "\n";
}
However, this is extremely dangerous because most integer arrays are not terminated by a zero and not all pointer to integers are arrays.
I think this has to do with operator <<
for char*
and int*
more than anything else. C programmers are used to null terminated strings printing out so a method was created to print them. int
s can be printed directly. A char
will not be able to print out a whole string.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.