Need help understanding array of pointers in C++

Thread Starter

integral

Joined Aug 19, 2010
22
Hello,
I need help understanding pointers, in particular in regards to an array of C-strings. I will like to direct your attention to the code segments with
headings // ***** Segment 1 Below ****** and // ***** Segment 2 Below ******.
I dont understand why I am getting the outputs I am getting for those code segments.
Here is my code (I am using visual studio 2005)


Rich (BB code):
#include <iostream>
#include <string>
using namespace std;

int main()
{
    // this is an array of pointers.  Each pointer points to a c style string
    char* names4[] = {"Dog", "Daniel", "Alex"};

    cout << "names4              : " << names4 << endl;
    cout << "*names4             : " << *names4 << endl;
    cout << "names4+1            : " << names4+1 << endl;
    cout << "*(names4+1)         : " << *(names4+1) << endl;
    cout << "names4+2            : " << names4+2 << endl;
    cout << "*(names4+2)         : " << *(names4+2) << endl;

    cout << endl;
    cout << "sizeof(names4)      :  " << sizeof(names4) << " bytes" << endl;
    cout << endl;

    cout << "names4[0]           : " << names4[0] << endl;
    cout << "names4[1]           : " << names4[1] << endl;
    cout << "names4[2]           : " << names4[2] << endl;
    cout << endl;

   // ***** Segment 1 Below ******
    cout << "(names4[0]) + 1     : " << (names4[0]) + 1 << endl;
    cout << "(*names4) + 1       : " << (*names4) + 1 << endl;
    cout << endl;

    // ***** Segment 2 Below *******
    cout << "(names4[1]) + 1     : " << (names4[1]) + 1 << endl;
    cout << "(*(names4+1)) + 1   : " << (*(names4+1)) + 1 << endl;

    return 0;
}
Here is the output I get
Rich (BB code):
names4              : 0018FF20
*names4             : Dog
names4+1            : 0018FF24
*(names4+1)         : Daniel
names4+2            : 0018FF28
*(names4+2)         : Alex

sizeof(names4)      :  12 bytes

names4[0]           : Dog
names4[1]           : Daniel
names4[2]           : Alex

(names4[0]) + 1     : og
(*names4) + 1       : og

(names4[1]) + 1     : aniel
(*(names4+1)) + 1   : aniel
Press any key to continue . . .
 

Thread Starter

integral

Joined Aug 19, 2010
22
I want to clarify my question:

If we look at
Rich (BB code):
cout << "(*names4) + 1       : " << (*names4) + 1 << endl;
If I understand correctly, the part in parenthesis is done first, so
Rich (BB code):
  (*names4)
evaluates to
Rich (BB code):
Dog
what then happens so that
Rich (BB code):
 Dog + 1
is evaluated as
Rich (BB code):
 og
 

someonesdad

Joined Jul 7, 2009
1,583
It is common for folks new to pointers to get confused by them. Two things that can help are:

  1. Make diagrams on paper using sequential boxes representing memory of the data in your program.
  2. Figure out exactly what's happening in each pointer statement. This means you e.g. have to read the material in K&R on pointers and understand both the syntax and semantics.
A real key truth is that it is best if you teach yourself -- the lessons will be much better learned. So I won't give any answers, but I'll hopefully give you some useful techniques.

The linear boxes can be used to draw a picture of what you have. You abstract things too so you can ignore implementation details and focus on concepts.

For example, you first can view the string array names4 as three boxes, each containing a pointer to a string somewhere in memory. It's not important that each of these boxes might in fact be some number of bytes holding an integer (this will depend on platform details).

Then you learn what something like *names4 means. First, you need to know its type. Then you should find out its value. You can do this either in the debugger or perhaps using printf with the %p spec. I recommend you use printf and learn how to find these things out without using a debugger, as one day you'll be faced with either a broken debugger or no debugger at all. Since you're using C++, you can do similar things with the output streams, but I still recommend you learn to use printf.

Now start figuring out what the type and values of the various expressions you're using are. For example, what is the type and value of names4[0]? Then what happens when you add 1 to it? Lest you think these are trivial questions, they're not -- and they may not have obvious answers until you know what's going on. Hint: learn what sizeof() does (things may be obvious for string pointers, but you'll need the knowledge when you deal with e.g. arrays of structures). Again, it's best if you have a good reference like K&R at hand.

Pick apart each expression. For example, if you don't understand what (*(names4+1)) + 1 yields, then examine the type and value of each step:

names4
names4+1
*(names4 + 1)
(*(names4+1)) + 1

This might strike you as too much work, but a beginning programmer only has to do it once or twice to learn what's going on. Trust me, it will be time well spent if you're going to do a bunch of pointer stuff. And you will have to use the tools again later in a program you're working on when you're not getting the results you want.

Finally, one of the best learning tools is to dump the assembly of the code you're working on. Even if you don't understand the details of the assembly language, you can usually puzzle out what's going on, like setting up stack frames for function calls, cleaning up after a function call, doing pointer arithmetic, etc. This can really help with understanding when the lines of C code are interspersed with the assembly. However, this might be a bit overwhelming now -- but if you're going to be doing a lot of C/C++ programming, it's something you should teach yourself.
 

Thread Starter

integral

Joined Aug 19, 2010
22
Thank you. I will do what you suggested.

After looking around, I figured I will need
Rich (BB code):
 #include <typeinfo>
and something of the sort:
Rich (BB code):
 typdeid(varName).name()
Is it possible to do the following with "printf" instead of "cout"? I not familiar with printf and after looking at it I am not sure if it can be done

Rich (BB code):
 cout << typeid(varName).name()
 

someonesdad

Joined Jul 7, 2009
1,583
You can use RTTI stuff if you want; however, I was thinking more along the lines of something like:
Rich (BB code):
#include <iostream>
#include <cstdio>
using namespace std;

int main() {
    int i = 12;
    int *p = &i;
    char *a[] = {"this", "is", "a", "string"};

    cout << "Using cout:" << endl;
    cout << "i = " << i << endl;
    cout << "&i = " << &i << endl;
    cout << "p = " << p << endl;
    cout << "*p = " << *p << endl;
    cout << "a = " << a << endl << endl;

    cout << "Using printf:" << endl;
    printf("&i = 0x%p\n", &i);
    printf("p = 0x%p\n", p);
    printf("a = 0x%p\n", a);
    printf("*a = 0x%p\n", *a);
    printf("**a = 0x%p\n", **a);

    cout << endl << "Dump string array's memory" << endl;
    cout << "a[0] " << a[0][0]
         << " " << a[0][1]
         << " " << a[0][2]
         << " " << a[0][3] << endl;
    cout << "a[0] using pointer arithmetic: "
         << endl
         << " " << *a << endl
         << " " << *a + 1 << endl
         << " " << *a + 2 << endl
         << " " << *a + 3 << endl;
    // etc., etc.
}
which, on my machine with g++ produces
Rich (BB code):
Using cout:
i = 12
&i = 0x22ff3c
p = 0x22ff3c
*p = 12
a = 0x22ff20

Using printf:
&i = 0x0022FF3C
p = 0x0022FF3C
a = 0x0022FF20
*a = 0x00444000
**a = 0x00000074

Dump string array's memory
a[0] t h i s
a[0] using pointer arithmetic:
 this
 his
 is
 s
By printing these things out, you'll learn a bit about how things get laid out in memory and how pointer arithmetic works. For example, note that **a prints out as hex 74, which is decimal 116, which corresponds to the ASCII letter 't'. This is the first letter 't' in the first string in a, the array of strings.
 
Top