Archived

This topic is now archived and is closed to further replies.

amemorex

the use of char** ?

Recommended Posts

Guest Anonymous Poster   
Guest Anonymous Poster
>It basically declares an array variable[][] but with ** you can dynamically allocate how big you want the array to be

Declaring a variable of type char** does not declare a two dimensional array. It declares a pointer to a pointer to a character. The reason why this may be thought of similar to an array is due to the following equivalent peices of code:

a[j];
*(*(a+i*sizeof(char))+j*sizeof(char));

You really don''t need the sizeof(char) part but I wanted it to be explicit.

Share this post


Link to post
Share on other sites
Oluseyi    2103
Once you understand the concept of pointers and indirection, then you'll come to see that more *'s simply means more levels of indirection.

But what is a pointer?
A pointer points at something (okay, that's like saying "to learn circular logic you must first learn circular logic," or "recursion: see recursion"). A pointer is a type of variable that holds the memory location of another variable. Pointers are declared with the indirection operator (*), which looks like a multiplication symbol but is interpreted differently. Example:
int *pInt;  

This declares a pointer to an integer. However, it also declares an integer.

How can you declare two separate things at once?!
pInt is a pointer to an integer; *pInt, however, is an integer. What I mean is that you can dereference a pointer - get to the variable (or object) it points to.
int an_int = rand() % 100; // get a random integer between 0 and 99
pInt = &an_int; // make our pointer point to 'an_int'
*pInt = 6;

Guess what that last line does? It sets the value of an_int to 6! Dereferencing - keep it in mind.

Okay, okay, how about indirection?
Indirection, as its name implies, refers to methods of accessing things indirectly. Take our pointer example from above; we accessed an_int through pInt - indirection. Indirection allows us to modify many different objects through one variable (which makes writing algorithms much more elegant, among other things), and is what happens with arrays.

Well, what the <your favorite expletive here> does this have to do with char **?!
Two levels of indirection. A pointer to a pointer; dereferencing the first pointer gives you the second, and dereferencing that gives you the object pointed to - a char in this case. This is how dynamic arrays (and indeed, all arrays at a much lower level) are implemented; the [] operator adds the subscript to the "base" pointer and dereferences the resulting pointer to get to an object.

Hopefully, this has helped you gain a basic comprehension of pointers and will enable you to manipulate them better in the future.

[Edit:] Highlighting.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!


Edited by - Oluseyi on December 13, 2001 12:57:07 AM

Share this post


Link to post
Share on other sites
JonStelly    127
Here's one example of pointers to pointers being useful:

    

class CUser
{
protected:
char m_szName[64];

//... other functions here ...//

public:
bool GetName(char **ppName)
{
(*ppName) = new char[strlen(m_szName)];
if((*ppName) == NULL)
return false;

strcpy((*ppName), m_szName);
return true;
}

void FreeName(char **ppName)
{
if(*ppName == NULL)
return;

delete (*ppName);
(*ppName) = NULL;
}

int main(...)
{
char *lpName;
CUser u;
if(u.GetName(&lpName))
{
cout << lpName << endl;
u.FreeName(&lpName);
}
}


Here I'm just using pointers to pointers to allocate and free a string inside of a function. Basically the above just keeps me from having to call member functions to see how large a buffer I need to allocate in main()...

Edited by - jonstelly on December 14, 2001 2:02:25 AM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
An example of when to use <type>** is when you want to return a reference to an object of <type>.

To show why it is necessary, take a look at this code snippet.
  
int getObject(Object *returnObject)
{
returnObject = new Object();
return 1;
}


The intent of the function is to retrieve a reference to a new Object. At first glance, this code may seem to do the job but is in fact wrong and contains a mistake that is very easy to make. The variable returnObject is a pointer to an Object, that is it is supposed to point to a block of memory that represents an Object. By calling returnObject = new Object() it is replacing the old pointer with a new one. However, when the function returns, the caller of the function still sees the old pointer! To remedy this problem the function needs to be rewritten as follows.
  
int getObject(Object **returnObject)
{
*returnObject = new Object();
return 1;
}


returnObject is now a pointer to a pointer to an Object. When the function is called, it dereferences returnObject and changes that value. This way the callee of getObject can dereference the value it passed in and get back the new Object that was allocated.

It can be a tricky concept and its difficult to explain but I hope you get the picture.

Share this post


Link to post
Share on other sites