tags:

views:

317

answers:

5

Embarrassing though it may be I know I am not the only one with this problem.

I have been using C/C++ on and off for many years. I never had a problem grasping the concepts of addresses, pointers, pointers to pointers, and references.

I do constantly find myself tripping over expressing them in C syntax, however. Not the basics like declarations or dereferencing, but more often things like getting the address of a pointer-to-pointer, or pointer to reference, etc. Essentially anything that goes a level or two of indirection beyond the norm. Typically I fumble with various semi-logical combinations of operators until I trip upon the correct one.

Clearly somewhere along the line I missed a rule or two that simplifies and makes it all fall into place. So I guess my question is: do you know of a site or reference that covers this matter with clarity and in some depth?

+2  A: 

I'm not sure exactly what you're looking for, but I find it helpful to remember the operator precedence and associativity rules. That said, if you're ever confused, you might as well throw in some more parens to disambiguate, even if it's just for your benefit and not the compiler's.

edit: I think I might understand your question a little better now. I like to think of a chain of pointers like a stack with the value at the bottom. The dereferencing operator (*) pops you down the stack, where you find the value itself at the end. The reference operator (&) lets you push another level of indirection onto the stack. Note that it's always legal to move another step away, but attempting to dereference the value is analogous to popping an empty stack.

Sean Devlin
+6  A: 

I don't know of any website but I'll try to explain it in very simple terms. There are only three things you need to understand:

  1. variable will contain the contents of the variable. This means that if the variable is a pointer it will contain the memory address it points to.
  2. *variable (only valid for pointers) will contain the contents of the variable pointed to. If the variable it points to is another pointer, ptr2, then *variable and ptr2 will be the same thing; **variable and *ptr2 are the same thing as well.
  3. &variable will contain the memory address of the variable. If it's a pointer, it will be the memory address of the pointer itself and NOT the variable pointed to or the memory address of the variable pointed to.

Now, let's see a complex example:

 void **list = (void **)*(void **)info.List;

list is a pointer to a pointer. Now let's examine the right part of the assignment starting from the end: (void **)info.List. This is also a pointer to a pointer.

Then, you see the *: *(void **)info.List. This means that this is the value the pointer info.List points to.

Now, the whole thing: (void **)*(void **)info.List. This is the value the pointer info.List points to casted to (void **).

Andreas Bonini
+3  A: 

Typedefs can be your friend when things get confusing. Here's an example:

typedef const char * literal_string_pointer;
typedef literal_string_pointer * pointer_to_literal_string_pointer;
void GetPointerToString(pointer_to_literal_string_pointer out_param)
{
    *out_param = "hi there";
}
Mark Ransom
A: 

All you need to know is that getting the address of an object returns a pointer to that object, and dereferencing an object takes a pointer and turns it into to object that it's pointing to.

T x;
A a = &x; // A is T*
B b = *a; // B is T
C c = &a; // C is T**
D d = *c; // D is T*

Essentially, the & operator takes a T and gives you a T* and the * operator takes a T* and gives you a T, and that applies to higher levels of abstraction equally e.g. using & on a T* will give you a T**.

Another way of thinking about it is that the & operator adds a * to the type and the * takes one away, which leads to things like &&*&**i == i.

Peter Alexander
+2  A: 

I found the right-left-right rule to be useful. It tells you how to read a declaration so that you get all the pointers and references in order. For example:

int *foo();

Using the right-left-right rule, you can translate this to English as "foo is a function that returns a pointer to an integer".

int *(*foo)();  // "foo is a pointer to a function returning a pointer to an int"
int (*foo[])();  // "foo is an array of pointers to functions returning ints"

Most explanations of the right-left-right rule are written for C rather than C++, so they tend to leave out references. They work just like pointers in this context.

int &foo;  // "foo is a reference to an integer"
Adrian McCarthy
caspin