I apologize in advance for the silliness of this question. But I couldn't find the way of understanding this outcome. I'm trying to figure out what the pointer really is in C++. Following is just a simple code printing an address in different ways.
int a = 15000;
char *b = reinterpret_cast<char*>(a); //equivalent of char *b = (char *)a
int *m = &a;
//(1)
printf("&a:%p\n",&a); //0x7fff5fbff878
printf("&*m:%p\n",&*m); //0x7fff5fbff878
printf("m:%p\n",m); //0x7fff5fbff878
//(2)
printf("a:%p\n",(int*)a); //0x3a98
printf("&*b:%p\n",&*b); //0x3a98
printf("b:%p\n",b); //0x3a98
printf("*m:%p\n",(int*)*m); //0x3a98
printf("&b:%p\n",&b); //0x7fff5fbff870
printf("&m:%p\n",&m); //0x7fff5fbff868
//(3)
std::cout << "b:" << b << std::endl; //error: Segmentation fault: 11
So the question is
why the address of (1) and (2) are different
why the size(length of address) of (1) and (2) are different
what happened when an int is cast to a char*
how 'b' could contain an address of 'a'
why the error (3) has occurred while 'printf("b:%p\n",b)' is working.
why the address of (1) and (2) are different
Because in the first example (1), you use the & address of operator, which gives you the address where the "a" variable is stored, example 0x50302040.
But the second example (2), you are using the value that address (0x50302040) points to, which returns 15000 which equals to 0x3a98 in hexadecimal.
what happened when an int is cast to a char*
If int has a value of 15000, now char* points to the address 15000, which is clearly wrong.
why the error (3) has occurred while 'printf("b:%p\n",b)' is working.
Because your pointer is a char* pointer, therefore the character sequence overload (ostream& operator<< (ostream& os, const char* s); is used, and since your pointer doesn't point to a character sequence (in fact, it doesn't point to anything since you assigned an invalid value to it), your program crashes.
Theres a ostream& operator<< (void* val); overload that will just print the address of the pointer, but you need to explicitly cast your char* pointer to a void* pointer to use it:
std::cout << "b:" << (void*)b << std::endl; // Prints 0x3a98 (15000)
Related
test code:
#include <iostream>
using namespace std;
int main()
{
const char* b="str";
cout << b << endl;
cout << *b << endl;
cout << &b << endl;
cout << *(&b) << endl;
return 0;
}
result:
str
s
0x7ffdf39c27f0
str
I run my code on the web runoob online compiler
Why I get these results? I looked some questions about char*, but not enough for me to understand. Can someone explain that to me? Pictures are best.
I want to know more about it with books or blogs recommended.
By the way, usingchar b[] instead of const char*, I get the same results.
Thanks a lot for all of you.
I just want to know why a char pointer's value is not an address.
I think adress is like 0x7ffdf39c27f0. an memory adress.
But const char* b = "str". b is just str.
And I found that *b is the same as *("str").
So I want to know what happened in the memory? why a char pointer's value is not an address?
To understand what the code outputs, you need to understand that C++ output streams (objects with a type such as std::ostream) and therefore objects (such as std::cout) have a number of overloads of operator<<(). The overload that is called depends on the type of argument provided.
I'll explain your second example, but the explanation for the first example is almost identical.
const char* b="st\0r";
cout << b << endl;
cout << *b << endl;
cout << &b << endl;
cout << *(&b) << endl;
cout << b expands to cout.operator<<(b) where b has type const char *. That overload of the operator function ASSUMES the argument points to (the first character of) a nul terminated string, which is represented in memory as an array of char that ends with a char with value '\0' (zero). The operator function outputs each character it finds until it reaches a '\0' character. The first '\0' found is the one YOU explicitly inserted after the 't', so the output st is produced. The fact that your string has a second '\0' after the 'r' is irrelevant, since the operator function stops at the first one it finds.
cout << *b expands to a call of a different overload of operator<<() that accepts a single char, and outputs that char. *b is the value of the first character in the string represented by b. So the output s is produced.
In cout << &b, &b has type const char ** or (equivalently) char const **. There is no overload of an output stream's operator<<() that accepts a const char **, but there is an overload that accepts a const void *. Since any pointer (other than pointer-to-member or pointers to functions) can be implicitly converted to void *, that conversion is performed (by the compiler), so the overload matches, and is called. That particular overload of the operator<<() prints the address in memory.
The implicit conversion in the third case doesn't happen in the first two cases, since a call that doesn't require an implicit conversion is a better match than a call which does.
In the last statement *(&b) is equivalent to b. This is the case because & is the address-of operator in this code, and the * is the dereference operator (which is the inverse of the address-of operator). So the last statement produces the same output as cout << b.
cout << b << endl;
You are printing the string b
cout << *b << endl;
You are printing the pointer that points to the first character of b., so is the same as:
cout << b[0] << endl;
cout << &b << endl;
&b is the memory address of b, which means the address memory to store b in the computer.
cout << &b << endl;
So, you're printing the memory address of b here. The computer store b in the memory address 0x7ffdf39c27f0, so that's what you get.
cout << *(&b) << endl;
You are printing a pointer that points to the memory of b, so you print the value at the memory address of variable b which is the same as
cout << b << endl;
edit: A pointer contains an address that (usually, it could point at a function, for example) represents the location of an object, and to print a pointer (usually) prints the value of that memory address. Because char * is intimately linked with null-terminated strings, there is a special overload for pointers to characters to print the pointed-at string.
A pointer variable is still a variable and will have an address of its own, so &b results in a pointer to a pointer, a char ** in this case and because it is no longer a char *, cout << &b; prints the address of b, not the address pointed at by b or the string pointed at by b.
This question already has answers here:
cout << with char* argument prints string, not pointer value
(6 answers)
Closed 5 years ago.
char p;
cout << &p;
This does not print the address of character p. It prints some characters. Why?
char p;
char *q;
q = &p;
cout << q;
Even this does not. Why?
I believe the << operator recognizes it as a string. Casting it to a void* should work:
cout << (void*)&p;
std::basic_ostream has a specialized operator that takes a std::basic_streambuf (which basically is a string (in this case)):
_Myt& operator<<(_Mysb *_Strbuf)
as opposed to the operator that takes any pointer (except char* of course):
_Myt& operator<<(const void *_Val)
This is because the pointer to char has its own overload of <<, which interprets the pointer as a C string.
You can fix your code by adding a cast to void*, which is the overload that prints a pointer:
char p;
cout << (void*)&p << endl;
Demo 1.
Note that the problem happens for char pointer, but not for other kinds of pointers. Say, if you use int instead of char in your declaration, your code would work without a cast:
int p;
cout << &p << endl;
Demo 2.
std::cout will treat a char* as a string. You are basically seeing whatever is contained in memory at the location of your uninitialised pointer - until a terminating null character is encountered. Casting the pointer to a void* should print the actual pointer value if you need to see it
This question already has answers here:
Why is address of char data not displayed?
(8 answers)
Closed 2 years ago.
Code Snippet :
#include <iostream>
int main()
{
char c = 50;
int i = 50;
std::cout<<&c<<"\n";
std::cout<<*(&c)<<"\n";
std::cout<<&i<<"\n";
return 0;
}
Expected output :
<memory_address>
2
<memory_address>
Original output :
2
2
0x7ffee0504ac4
Confusion :
I thought & in this case should return the reference of the variable, printing which (according to me) should give me a memory address, which turns out to be true with variables of other data type like int,float and double
then why in the case of type char, it is displaying the value in it ?
compiler = clang-1103.0.32.62
Its because of overload for operator<< (const char*) for ostream.
&c is of type char* and the operator<< tries to print 0-terminated C-string.
If you cast to void* as (void *)(&c) then you will get memory address as expected:
#include <iostream>
int main()
{
char c = 50;
int i = 50;
std::cout<<&c<<"\n"; // this will try to print null-terminated char* string.
std::cout << (void*)(&c) << "\n"; // this will print memory address as expected
std::cout<<*(&c)<<"\n";
std::cout<<&i<<"\n";
return 0;
}
Note: cout << &c may print some more characters, depending what bytes are present behind memory address &c ( the 0-byte could be far behind). So this is basically undefined behavior (UB).
There are no references in your code. & is the address-of operator which returns a pointer not a reference. & only means reference when it's used in a declaration, not when it's used in an expression.
The reason you get different results for &c and &i is that operator<< has an overload for char* which assumes that the argument is a C string. Since that's not the case for you, your program actually has undefined behaviour.
So i want to point a pointer to a character and then output the address put it outputs this weird thing: t+ a. Any help?
#include <iostream>
using namespace std;
int main() {
char a = 't';
char* p = &a;
cout << p;
return 0;
}
You are printing a char* type, which the cout tries to interpret as a string.
Print the value of the pointer (The address it points to) using:
cout << (void *)p;
-- OR --
cout << static_cast<void *>(p);
The problem is that char * is conventionally not just used as a pointer to a char, but a pointer to a null-terminated C-string instead. cout will then print all the characters pointed to by p until it finds a '\0', so you get to see the t and then it prints invalid memory which is undefined behavior which may crash or print garbage or something else.
The way to fix this is to use void * or maybe const void * instead which is just a pointer with an address but no type information attached. void *p = &a; would be one fix. void *p2 = p; and then using std::cout << p2; would be another. You can also use a cast as shown in the other answer, except you should be using a C++ cast like static_cast<const void*>(p) instead of a C cast like (void *)p because once you get used to them they become easier to read and reason about.
If you want address of the pointer, either cast it to void pointer
std::cout << (void *)p;
or use printf with %p option
printf("%p", p);
Otherwise it will be treated as null terminated string, which it is not.
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
int *ab;
*ab = 5656;
cout << *ab; //These block crashes the app too.
But i can get the hex value of content of pointer if i write this:
int *ab = (int *)5656;
cout << ab; //Output is hex value of 5656.
So i want to ask: * is a operator that brings the contents of pointer(?) but why in this(these) example(s) app crashes?
And i can use that operator if i change code into this:
int a = 5656;
int *aptr = &a;
cout << *aptr; //No crash.
And why dereference operator(*) brings the only first character of a char:
char *cptr = "this is a test";
cout << *cptr; // Here output = 't'
cout << cptr; // Here output = 'this is a test'
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
In this case, you are setting the pointer ab to point at the address 5656. Do you know what's at this address? No you don't. You are telling the compiler to trust you that there is an int there. Then, when you dereference the pointer with *ab, you obviously find that there isn't an int there and you get undefined behaviour. In this case, your program crashes.
int *ab;
*ab = 5656;
cout << *ab;
In this case, you have an uninitialised pointer ab which you then dereference to assign 5656 to the int it points at. Since it's uninitialised, dereferencing it gives you undefined behaviour. Think of it this way. You haven't put an addres in ab so you don't know where it points. You can't just dereference it and hope it points at an int.
int a = 5656;
int *aptr = &a;
cout << *aptr;
This is fine because you know you have an int object with value 5656 and you know that aptr contains the address of that int object. It's perfectly fine to dereference aptr.
const char *cptr = "this is a test";
cout << *cptr; // Here output = 't'
cout << cptr;
(Your code was using a deprecated conversion to char*, so I changed it to a const char*.)
The string literal "this is a test" gives you an array containing const chars. However, it then undergoes array-to-pointer conversion giving you a pointer to its first element. Since each element is a const char, the pointer you get is a const char*. You then store this pointer in cptr.
So cptr points at the first element of the string. Dereferencing that pointer gives you that first element, which is just the first character of the string. So you output t.
The I/O library has special overloads that take const char*s and treat it as pointing to a string of characters. If it didn't, cout << cptr would just print out the address in cptr. Instead, these special overloads will print out the null-terminated array of characters that cptr is assumed to point to.
I think it's worth noting that the application crashes you are observing are due to the fact that it is very unlikely that your process (i.e. program) owns the memory at the location you specify: 5656.
Modern operating systems disallow access to memory allocated by other processes.
Imagine what a headache it would be if that we're not the case: one program could modify the data associated with another one!
The "access violation" message is a helpful hint that you're accessing memory that your process does not own.
is a operator that brings the contents of pointer(?)
No. * is a operator that brings the contents of memory which pointer point to.
Here:
int *ab = (int *)5656;
cout << *ab; //Here appcrash.
Pointer ab contains 5656. *ab tries to access memory which pointer ab point to => *ab tries to access memory at address 5656. Your program is not allowed to access memory at address 5656 because it is not allocated or read-only => app crashes.
And i can use that operator if i change code into this:
int a = 5656; int *aptr = &a; cout << *aptr; //No crash.
Here you allocate and initialize memory: int a = 5656;
Here you write address of previously allocated memory to pointer: int *aptr = &a;
Here you access memory which was previously allocated: *aptr (memory contains 5656).
You have right to access it => app doesn't crash.
And why dereference operator(*) brings the only first character of a char
Because char is not string, char is character. When you dereference pointer to char, you get char.
C has no built-in type for string. That's why it's common to use pointer to memory containing string. This pointer usually points to a first character of string: char * - pointer to character