简体   繁体   中英

pointer to char vs pointer to arrays

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 have bonjour as output and 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 ?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM