This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does cout print char arrays differently from other arrays?
If I have this code:
char myArray[] = { 'a', 'b', 'c' };
cout << myArray;
It gives me this output:
abc
However, if I have this code:
int myArray[] = { 1, 2, 3 };
cout << myArray;
It gives me this output:
0x28ff30
Why does it not print out 123?
The reason that the first piece of code works is that the compiler is implicitly converting the array into a const char * character pointer, which it's then interpreting as a C-style string. Interestingly, this code is not safe because your array of characters is not explicitly null-terminated. Printing it will thus start reading and printing characters until you coincidentally find a null byte, which results in undefined behavior.
In the second case, the compiler is taking the int array and implicitly converting it into an int * pointer to the first element, then from there to a const void * pointer to the first element. Printing a const void * pointer with cout just prints its address, hence the output you're getting.
Hope this helps!
There is an operator << that knows about basic_ostream instances (such as cout) on the left-hand-side and const char*s on the right.
There is no such operator defined for const int* (or const int[]). Although you are perfectly at liberty to create one.
Just be sure to specify a sentinel at the end of your arrays to prevent running off the end of your buffer.
The reason you see the pointer value is because there is an basic_ostream::operator<<(const void*) which will print this.
std::cout is an instance of std::ostream, and there are several overloaded operators provided.
For example:
std::ostream& operator << (std::ostream&, char*);
When you type std::cout << somevar; compiler looks up best matching overload. First for exact type of the variable, then for anything it can be implicitly converted to (not to mention member functions/free functions/template functions, etc).
Here is a random article on C++ Overload Resolution
When you use myArray in the context cout << myArray;, it decays to a pointer. The operator<< which takes a char* as its second argument outputs a string; the one which takes other types of pointer just outputs an address. Hence the observed behaviour.
Your char array is actually not null-terminated, so I guess what you're seeing in the first case is really just undefined behaviour which happens to do 'the right thing' in this instance.
You haven't passed it an array of ints; you've passed it a pointer to an int. When faced with a pointer, it prints out the address that it points to. It has no way of printing out an array because it doesn't know how many elements it has (if any).
The reason it worked when you used a pointer to a character is that it knows that all arrays of characters are terminated by a NUL (\0) character, so it doesn't matter that you haven't told it the number of characters in your array. Keep in mind that your array is not terminated by a NUL, so it's only by luck that you got abc and no extra garbage characters on the end.
Because it has no way of knowing that your array is an array, or what kind of data is in it. When you do cout << myArray, 'myArray' is treated as a pointer type, which may point to anything. So instead of trying to dereference the pointer (and potentially crashing the app if the pointer has not been initialized), the address that the pointer is pointing to gets printed.
Related
If I execute this code:
#include<iostream>
using namespace std;
int main(){
char str[20] = {'a','b','c','d','e'};
cout<<str<<endl;
return 0;
}
It outputs abcde but If I execute this code:
#include<iostream>
using namespace std;
int main(){
int arr[20] = {1,2,3,4,5};
cout<<arr<<endl;
return 0;
}
It outputs 0x7fff22eecc30 I have tried executing this code in two different online compilers and they are giving same outputs.
In char array it is returning the array contents but in int array it's returning memory address. Why is that? Also, how can two different online compilers return the same memory address?
I have tried looking out online for this but I'm not sure what to look for?
With char str[20] = {'a','b','c','d','e'};, the remaining 15 elements of the array are all set to 0. The special ostream overload for << that's used as a result of the array str decaying to a char* pointer to the first element of that array will output the array as if it's a C-style string, since the first 0 will act as a NUL terminator.
An equivalent way of writing the above is char str[20] = "abcde".
In your second case, the overloaded << for ostream for a const void* pointer is used (due again to pointer decay), which prints the address of the first element of the array.
What std::cout knows how to print
Under the hood cout is an object derived from the basic_ostream class template. The standard library provides some functions that tell basic_ostream how to print different types of data. (Some are member functions, some aren't - but that's not important here.)
Here are some examples:
basic_ostream<charT,traits>& operator<<(bool n);
basic_ostream<charT,traits>& operator<<(short n);
basic_ostream<charT,traits>& operator<<(int n);
basic_ostream<charT,traits>& operator<<(double f);
... and more ...
These functions tell cout (and other basic output streams) how to print bools, shorts, ints, etc.
There's also these two
basic_ostream<charT,traits>& operator<<(const void* p);
template<class traits>
basic_ostream<char,traits>&
operator<<(basic_ostream<char,traits>&, const char*);
The first one tells cout how to print the address of an untyped pointer (a void*).
The second one is intended to print C-style strings --- especially literal strings in your source code. For example, cout << "Hello";
What about arrays?
The standard library doesn't provide any direct support for printing arrays (or any other collection). If you want to print a collection, you have to decide what format you want for that collection, and code it up yourself.
This is the same for structs and classes. If you define your own class, cout doesn't know how to print it --- you must code that up yourself.
Why does your first example output "abcde"?
You're trying to print a char[20] (an array of char). basic_ostream doesn't have an overloaded << function for arrays, so it doesn't know how to print them.
BUT - C++ is allowed to implicitly cast an "array of T" to a "pointer to T", so your str variable is implicitly cast from char[20] to char*. That matches the last overload I listed above - the one that is supposed to be used for C-style strings. (Other answers have already discussed issues regarding the terminating zero that C-strings are supposed to have.)
What about the second example?
The type of arr is int[20]. Once again, cout doesn't know how to print arrays.
SO - C++ tries implicitly casting your int[20] to an int*. But there is no overload for int*, so C++ tries again. It implicitly casts the int* to a void* (which it is allowed to do) - and now it finds a match.
The void* overload prints the memory address of the pointer.
This happens with all arrays except arrays of char, signed char and unsigned char. The array of T is cast down to a pointer to T, which is cast down to a void pointer.
Why is char* treated differently than any other pointer type
Because we print C-style strings (especially string literals) a lot. Like, a lot a lot.
The most often usage of character arrays is the usage them as containers of strings. It is very easy to determine the size of a string due to its sentinel value that is the terminating zero character.
So if in a C program you will write for example
char str[20] = {'a','b','c','d','e'};
printf( "%s", str );
then the call of printf easy outputs the string "abcde" because it is well-knowb where to stop outputting characters of the character array.
If in a similar call of printf you will specify an integer array then it is unknown what is the size of the integer array. How many integers stored in the array to output?
So a call of printf for character arrays containing strings is well-defined. However if you are using a pointer of the type int * when it is unclear whether the pointer points to a single integer or a sequence of integers. And if the pointer points to a sequence of integers then what is the length of the sequence?
This approach was carried over to the implementation of the overloaded operator << for character arrays in C++.
Pay attention to that if a character array does not contain a string this such a statement
std::cout << str;
results in undefined behavior. In this case you should use for example the following call
std::cout.write( str, sizeof( str ) );
So i was reading the learncpp tutorial, and i was trying to print the address of a char pointer, because when you do :
char c{'i'};
cout << &c << endl;
It will just print the string "i", because i guess the compiler identify a char pointer to a char array, which is a string (however i don't understand why it's just printing "i", because there is not '\0' after the character 'i').
Anyway, i then tried to static_cast the char pointer into an int pointer so that is will print the address :
char c{'i'};
cout << static_cast<int*>(&c) << endl;
But this doesn't even compile, i have an error "invalid static_cast from the type << char* >> to the type << int* >>".
Finally, i simply tried a C-type cast like this :
char c{'i'};
cout << (int*)(&c) << endl;
And it works, it prints an address.
So my questions are :
why the static_cast doesn't work ? Is there any way to make a valid "C++ style cast" from char* to int* ?
in the first example, when I "cout << &c", why does it only print "i", while i haven't put any '\0' after the character 'i' ?
Thanks
Firstly, the static_cast<int*>(&c) will fail because static_cast only allows a very specific subset of type conversions. For instance, you can static_cast between numeric types, or between two class types which are related by inheritance (i.e. one inherits the other at some point in the inheritance hierarchy).
What you're doing is simply trying to "reinterpret" the address as an address to a different type. The reason being that C++ std::ostream overloads operator<< for const char*. If you only want to print the address itself, standard convention is to convert to void* via static_cast<void*>(&c) or just (void*)&c if you're ok with C-style casts. void* is basically a pointer with no type information, which makes it perfect if all you want to do is print out the value of the address itself.
The reason the C-style case compiles is because a C-style cast employs very ... shall we say risky ... methods to perform the conversion. It's allowed to perform const_cast, reinterpret_cast, and static_cast - whatever is necessary - in order to perform the cast you specified. This behavior is detailed on cppreference.com.
As for why the example of printing the char* directly only prints a single character despite not being terminated: undefined behavior is undefined. Apparently, it just so happens that (with this compiler) the executable happens to have a zero (null) byte immediately following it, wherever it may be. The compiler might even realize you assign a value but never modify it, so it might not even be in the stack (it might be in the data segment of the executable). The moral of the story is just not to invoke undefined behavior.
Let me give an example. Printing address is same as printing pointer. Such as
Int* a;
cout<<a;// print the address Lets look another
Int a;
cout<<&a; // print the address, after casting into int*
Both are same.
Now take similar case for char, and look what happen
char a = 'a'
cout<<&a; // it is printing value of *a means char* a
So that's why &a prints the value of char rather than address, because printing the address of char, after casting, char becomes the char* which is the data type called char pointer.
Consider the output of this code:
char A = 'a';
char B[] = "b";
cout<<&A;
It outputs "ab" (the concatenation of A and B) and I wonder why. Please, explain me this.
Because &A is a char *. A string, represented by a char *, is required to have a '\0' terminating byte.
&A points to a single char, without a following '\0'. As such, attempting to print this text string results in undefined behavior.
You got an unexpected result because the operator << for objects of type char * is overloaded such a way that it outputs strings pointed to by pointers of the type char *.
It seems that your compiler placed the array B after the character A and in the memory they look like one string.
'a' 'b' '\0'
| |
A B
(It is unspecified in the C++ Standard whether A will precede B or B will precede A in the memory and whether there will be a gap due to padding bytes between the objects.)
If you want to output the address of the object A you should write for example
cout<< ( void * )&A;
or
cout<< ( const void * )&A;
or either ,like
cout<< static_cast<void *>( &A );
or like
cout<< static_cast<const void *>( &A );
It is unimportant whether the const qualifier will be specified for the pointer to a non-constant object because. It will be implicitly converted to the type const void * in the operator
basic_ostream<charT,traits>& operator<<(const void* p);
cout expects the char* parameter to point to a zero terminated string. But &A isn't zero terminated, so the precondition fails and this leads to undefined behavior.
Undefined behavior cannot really be explained, because the standard allows anything to happen. Displaying some more characters is one possible result. As is crashing. Or something else.
I wonder why
Because the stream insertion operator requires that any character pointer passed to it must point to a null terminated character string. The pointer passed to cout points to A which is not a null terminated character string. Since the pre-conditions (requirements) of the operation were not satisfied, the behaviour is undefined.
There are two relevant overloads for insertion operator (I've simplified away the template details, and the fact the one of these is a member overload, and the other is not):
ostream& operator<< (const void*);
ostream& operator<< (const char*);
All other pointers implicitly convert to void* and use the former overload and the pointer is outputed as a memory address. But the latter is favoured overload for character pointers, and the argument is required to be a null terminated string.
So, because a character pointer is interpreted as null terminated string, the naïve attempt to print the address of a character does not work. The solution: Cast the pointer to void* explicitly before passing to the stream.
The streams have been designed this way, in order to conveniently support null terminated strings, such as string literals which were considered to be (and are) streamed more typically than addresses. For example, it is convenient that std::cout << "Hello World!";. Prints "Hello World" instead of a memory address where the string literal is located.
This is a compiler-dependent behavior. Often, A nad B will be allocated one after the other on the stack. Taking the address of A will look like the zero-terminated string "ab". Don't do this! You rely on the stack frame layout the compiler is constructing.
because your char is not null terminated.
The behavior for this will UNDEFINED.
Your compiler has placed string comprising 'b' and '\0' immediately after character 'a' so once you've printed your A character as a string it found 'a', followed by 'b' followed by '\0' hence you have printed 'ab'
This question already has answers here:
cout << with char* argument prints string, not pointer value
(6 answers)
Closed 8 years ago.
Today i have learned about pointers and i have this:
char message[]="hello everyone";
char *pm;
pm=message;
cout<<&pm[0];
This would output hello everyone, I want to know why? because & should output the address of pm[0] not the hole value. Can someone explain?
&pm[0] is of type char*. << is overloaded for char const* to print all characters until '\0'. If you want to print the address you have to convert it to void* first.
message is an array of chars containing hello everyone\0.
When you do pm = message;, the array message undergoes array-to-pointer conversion, which gives you a pointer pointing at the first element in the array. So pm now points at the very first char in the array (the h character).
pm[0] is equivalent to *(pm + 0), which basically just gives you the first character in the array. Then &pm[0] is taking the address of that character, giving you a pointer to the first character. So pm and &pm[0] are exactly the same.
cout has a special overload for handling char*s. When you pass a char* to cout, it assumes that you want it to print it out like a C-style string, where the char* is pointing at the first character in an array of characters that end with \0.
&pm[0] is the same as &(*(pm+0)) which is the same as &(*pm) which is the same as pm. And pm points to the first element of the zero-terminated character array message.
Now, the << operator for the output stream, when passed a char* or const char* treats that as a pointer to a null-terminated array of characters. That is, a C string.
So, the entire contents of the string are output to the output stream.
& should output the address of pm[0]
No, the & operator is not related to the output. The & operator is part of the expression &pm[0]. This expression is evaluated, as described above. And the result of that evaluation is passed to the best matching overload of the output stream's << operator. It is the << operator that determines how the value of your expression is output, and that determination is based on the type of your expression.
In order to output an address, you would need to supply an argument of a different type, for instance void*. You can cast the char* pointer like this:
static_cast<const void*>(&pm[0])
Usually, giving a pointer to std::cout will result in the pointer's value (the memory address it contains) being printed.
However, there is a special case for [const] char*, which is automatically assumed to be a C-style string and therefore dereferenced to be treated like one. This (in concert with array name decay) is to allow you to do things like std::cout << "Hello world\n"; without just getting a memory address instead.
The nearest question on this website to the one I have had a few answers that didn't satisfy me.
Basically, I have 2 related questions :
Q. If I do something like :
char a[]= "abcde"; //created a string with 'a' as the array name/pointer to access it.
a[0]='z'; //works and changes the first character to z.
But
char *a="abcde";
a[0]='z'; //run-time error.
What is the difference? There is no "const" declaration, so I should be free to change contents, right?
Q. If I do something like :
int i[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i; //'i' is a pointer to i[0], so I'm incrementing it and want to print 20.
This gives me a compile-time error, and I don't understand why.
On the other hand, this works :
int *i=new int[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i; //Prints 20.
Thanks for the help.
Q
char *a="abcde";
a[0]='z'; //run-time error.
Ans - Here a is pointing to string literal stored in read only location. You cannot modify string literal
Q
int i[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i;
Ans- Array and Pointers are not same thing. Here i is not a pointer.
You need lvalue for increment operand
You can do :
int *p = &i[0];
std::cout<<*++p;
In last case operator new returns a pointer to a allocated memory space, so its possible.
Question 1
The trouble is that it is still const.
A string literal actually has the type char const*.
But when they designed C++03 they decided (unfortunately) that conversion from char const* to char* is not an error. Thus the code:
char *a="abcde";
Actually compiles without error (even though the string is const). BUT the string literal is still a const even though it is being pointed at via a non const pointer. Thus making it very dangerous.
The good news is that most compilers will generate a warning:
warning: deprecated conversion from string constant to ‘char*’
Question 2
cout<<*++i; //'i' is a pointer to i[0], so I'm incrementing it and want to print 20.
At this point i is not a pointer. It's type is still an array.
It is not a valid operation to increment array.
The thing you are thinking about; is that arrays decay into pointers at the drop of a hat (like when you pass them to functions). Unfortunately that is not happening in this situation and thus you are trying to increment an array (which does not make sense).