C++ Pointers and arrays

Sade
Sade used Ask the Experts™
on
I know this may seem trivial to some...

I have the following code:

        char c[10]={"Hello All"};
     char *pc = &c[2];
     
        cout<<pc<<'\n';

why does 'pc' return "llo All", instead of a hex address.

If you do the following you get a hex address:
int num[]= {4,4,4};
     int *pnum = &num[4];

     cout<<pnum<<endl;

why is this happening?

Thanks
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
c is actually an address in memory that is 10 bytes long.  When you say &c[2], you say go to the 3rd element in c (since it is 0-based) and give me the address of that element.  At this point, you have a pointer to the 3rd element, so when you do the "cout << pc", you print the array starting at the 3rd element.  char *'s are special in that they are character arrays.  When you print a char *, the system expects you to print a string.  If you print the address of any other type, you actually print the address (which you could do with a char * by casting it to a long, like "cout << (long)pc << '\n';").

When you print the address of the element in the int array, the system acts the way that it does with any other plain old data type and prints the address.  By the way, the int array portion of your code is actually invalid because you are trying to print the address of the 5th element of a 3 element array.  It doesn't break because you are just printing the address, but if you tried to mess with the data there, some bad things could happen.  You don't own that memory, so you might be modifying part of one of your own variables (which will give you weird results), you might be playing with operating system memory or another task's memory (which will give you an access violation), or you may get lucky and be playing with memory that's not used by anyone.  Be very careful when messing with memory directly.  There's not a seasoned C/C++/assembly developer out there that hasn't spent days tracking down a strange problem that occurred when they overwrote memory that they didn't mean to.

Author

Commented:
Thanks! you're a star.
Good question, Sade

The reason is because is because of somthing called 'type-casting'.  C/C++ are very strict about type-casting. Also how you delcare a varible defines how it is passed durring an expression such as your cout expression, but this much im sure you knew.  

First off I'll answer your question as simple as I can and then I'll explain why it works that way.

All you have to do is type-cast your expression and you will get an entirely different result, without having to change the declaration of your variable.

Plus there are stream modifiers you can use to change the base number system the output stream will use to show your information.

For example:

//Your code
char c[10]={"Hello All"};
char *pc = &c[2];
   
//Prints "lo All"
cout << pc << '\n';

//So will this
pc = (c + (sizeof(char) * 3));
cout << pc << '\n';

//Reset to your example
pc = &c[2];

//Print the HEX address of the pointer
cout << hex << (void *)pc << endl;
//the hex modifier tells the stream we are
//going to want it in hexidecimal
//and then we type cast (void *) so it knows
//we want to print the address of a pointer
//i use a void pointer because it applies
//to *any* type of pointer, it will always
//print the address.
//using endl is like using '\n' but it also
//flushes the buffer and appears cleaner
//in the code in my opinion


//Print the VALUE of the data the pointer
//points to
cout << pc << endl;
//no type casting is neccessary because pc
//is of type (char *) and the ostream recognizes
//that the values contained inside are represented
//as ASCII characters and not integer values
//and will display it properly - common terms, a string.

//Now to really get your brain going, we can assign
//an INT pointer to your character array
int *a_ptr = (char *)c;

//And now we have an integer typed pointer pointing
//to a character typed pointer
//a character array is merely an array of numbers
//those numbers represent the ASCII value of the symbol
//for which it stands
//so with type casting we can do this
cout << (char *)a_ptr << endl;
//and we get the string!

-----------------

Now to address the second example you listed.

Firstly, this is dangerous:
 int num[]= {4,4,4};
 int *pnum = &num[4]; //Uh oh! num[4] doesn't exist!
 //in fact, nither does num[3].  Only num[0] to num[2]
 //are valid.  You can assign the pointer in
 //the following ways
 
 //this is equivalent to
 int *pnum = &num[0];
 //this
 int *pnum = num;


 //this is equivalent to
 int *pnum = &num[2];
 //this
 int *pnum = (num+(sizeof(int) * 2));


You are assigning the pointer to an uninitilized and most likely, invalid, portion of memory.  But that doesn't answer you why you still get the hex address.

The reason you get the hex address in this example is because it is of type (int *).  When you go to print it the overloaded operator recognizes this and prints the address of the pointer.  If it were (char *) it handles that differently because it has been told that, as i mentioned previously, that the value is a string.

You could type cast your example to a (char *) (once properly reassigned) and get the ASCII value of 4 printed on the screen, but you wouldnt see much since ASCII 4 is a diamond symbol.  But take care in doing this since your array is not terminated by a NULL (ASCII 0) character.

This should answer your question but I hope it didn't leave you more confused than when you started.  What you asked isn't trivial and a lot of programmers, even intermediate to so called advanced ones, don't realize how type-casting really does work and how much you can bend (even break) the rules to accomplish what you need.

Plus your question involved pointers and they are not a simple subject either.  I love pointers but they are extremely, extremely dangerous even to a veteran programmer, it is always easy to over-write, forget to unallocate, not check for NULL, etc.

Good luck and have a great day.

Thanks,
blackwolf359
Dustin Juliano

Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Son of a B*@#@, I went to eat dinner then came back to finish typing my answer and your question was already answered.. what a waste of time... how annoying.

Well at least you get two views on it.
I'm glad I could help.  Sorry blackwolf; I don't mean to take your question.

Author

Commented:
Thanks blackwolf, your answer was really thorough. Soz, I couldn't give you the points.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial