tags:

views:

1708

answers:

13

When does using pointers in any language require someone to use more than one, let's say a triple pointer. When does it make sense to use a triple pointer instead of just using a regular pointer?

For example:

char  * * *ptr;

instead of

char *ptr;
+2  A: 

N-dimensional dynamically-allocated arrays, where N > 3, require three or more levels of indirection in C.

Matt J
Chris Lutz
This is a little misleading because myarray[0][1][2] is often not actually 3 pointer indirections (though it could be). The memory is typically contiguous and the compiler does the arithmetic for you.
jw
Does the edit above resolve your concern? That is, can we agree that dynamically-allocated 3+-dimensional arrays require dereferencing 3+ pointers?
Matt J
A: 
 int main( int argc, char** argv );
tpdi
I think it is somewhat more idiomatic to write char* argv[]. That is, an array of char pointers. But then we get into the whole "array vs. pointer" debacle (:
jw
"Do you consider the eating of oysters to be moral and the eating of snails to be immoral? Of course not. It is all a matter of taste, isn't it? And taste is not the same as appetite, and therefore not a question of morals.... My taste includes both snails and oysters."
tpdi
A: 

A standard use of double pointers, eg: myStruct** ptrptr, is as a pointer to a pointer. Eg as a function parameter, this allows you to change the actual structure the caller is pointing to, instead of only being able to change the values within that structure.

Not Sure
A: 

If you have to modify a pointer inside a function you must pass a reference to it.

ojblass
+4  A: 

A pointer is simply a variable that holds a memory address.

So you use a pointer to a pointer, when you want to hold the address of a pointer variable.

If you want to return a pointer, and you are already using the return variable for something, you will pass in the address of a pointer. The function then dereferences this pointer so it can set the pointer value. I.e. the parameter of that function would be a pointer to a pointer.

Multiple levels of indirection are also used for multi dimensional arrays. If you want to return a 2 dimensional array, you would use a triple pointer. When using them for multi dimensional arrays though be careful to cast properly as you go through each level of indirection.

Here is an example of returning a pointer value via a parameter:

//Not a very useful example, but shows what I mean...
bool getOffsetBy3Pointer(const char *pInput, char **pOutput)
{
  *pOutput = pInput + 3;
  return true;
}

And you call this function like so:

const char *p = "hi you";
char *pYou;
bool bSuccess = getOffsetBy3Pointer(p, &pYou);
assert(!stricmp(pYou, "you"));
Brian R. Bondy
could you comment the getOffsetBy3Pointer method because i dont understand how the double pointer went to a single pointer
Jake
*pOutput has type char*. Just like with int **p; *p is of type int *.
Brian R. Bondy
A: 

It makes sense to use a pointer to a pointer whenever the pointer actually points towards a pointer (this chain is unlimited, hence "triple pointers" etc are possible).

The reason for creating such code is because you want the compiler/interpreter to be able to properly check the types you are using (prevent mystery bugs).

You dont have to use such types - you can always simply use a simple "void *" and typecast whenever you need to actually dereference the pointer and access the data that the pointer is directing towards. But that is usually bad practice and prone to errors - certainly there are cases where using void * is actually good and making code much more elegant. Think of it more like your last resort.

=> Its mostly for helping the compiler to make sure things are used the way they are supposed to be used.

Till
+21  A: 

each star should be read as "which pointed to by a pointer" so

char *foo;

is "char which pointed to by a pointer foo". However

char *** foo;

is "char which pointed to by a pointer which is pointed to a pointer which is pointed to a pointer foo". Thus foo is a pointer. At that address is a second pointer. At the address pointed to by that is a third pointer. Dereferencing the third pointer results in a char. If that's all there is to it, its hard to make much of a case for that.

Its still possible to get some useful work done, though. Imagine we're writing a substitute for bash, or some other process control program. We want to manage our processes' invocations in an object oriented way...

struct invocation {
    char* command; // command to invoke the subprocess
    char* path; // path to executable
    char** env; // environment variables passed to the subprocess
    ...
}

But we want to do something fancy. We want to have a way to browse all of the different sets of environment variables as seen by each subprocess. to do that, we gather each set of env members from the invocation instances into an array env_list and pass it to the function that deals with that:

void browse_env(size_t envc, char*** env_list);
TokenMacGuy
+1 for thinking up a plausible example.
RBerteig
A: 

Functions that encapsulate creation of resources often use double pointers. That is, you pass in the address of a pointer to a resource. The function can then create the resource in question, and set the pointer to point to it. This is only possible if it has the address of the pointer in question, so it must be a double pointer.

jalf
A: 
jw
+2  A: 

You use an extra level of indirection - or pointing - when necessary, not because it would be fun. You seldom see triple pointers; I don't think I've ever seen a quadruple pointer (and my mind would boggle if I did).

State tables can be represented by a 2D array of an appropriate data type (pointers to a structure, for example). When I wrote some almost generic code to do state tables, I remember having one function that took a triple pointer - which represented a 2D array of pointers to structures. Ouch!

Jonathan Leffler
A: 

Pointers to pointers are rarely used in C++. They primarily have two uses.

The first use is to pass an array. char**, for instance, is a pointer to pointer to char, which is often used to pass an array of strings. Pointers to arrays don't work for good reasons, but that's a different topic (see the comp.lang.c FAQ if you want to know more). In some rare cases, you may see a third * used for an array of arrays, but it's commonly more effective to store everything in one contiguous array and index it manually (e.g. array[x+y*width] rather than array[x][y]). In C++, however, this is far less common because of container classes.

The second use is to pass by reference. An int* parameter allows the function to modify the integer pointed to by the calling function, and is commonly used to provide multiple return values. This pattern of passing parameters by reference to allow multiple returns is still present in C++, but, like other uses of pass-by-reference, is generally superseded by the introduction of actual references. The other reason for pass-by-reference - avoiding copying of complex constructs - is also possible with the C++ reference.

C++ has a third factor which reduces the use of multiple pointers: it has string. A reference to string might take the type char** in C, so that the function can change the address of the string variable it's passed, but in C++, we usually see string& instead.

coppro
A: 

When you use nested dynamically allocated (or pointer linked) data structures. These things are all linked by pointers.

sybreon
A: 

Char *** foo can be interpreted as a pointer to a two-dimensional array of strings.

Pat