Reputation: 381
I am looking at some code I did not write and wanted help to understand an element of it. The code stores character arrays, creates pointers to these arrays (assigning the pointers the arrays addresses). It looks like it then creates an array to store these characters pointers addresses and I just wanted some clarification on what I am looking at exactly. I also am confused about the use of the double (**) when creating the array.
I have included a stripped down and simplified example of what I am looking at below.
char eLangAr[20] = "English";
char fLangAr[20] = "French";
char gLangAr[20] = "German";
char* eLangPtr = eLangAr;
char* fLangPtr = fLangAr;
char* gLangPtr = gLangAr;
char **langStrings [3]=
{
&eLangPtr,
&fLangPtr,
&gLangPtr
};
When using the array they pass it as an argument to a function.
menu (*langStrings[0]);
So the idea is that the character array value "English" is passed to the function but I'm having trouble seeing how. They pass the menu function a copy of the value stored in the langStrings function at location 0, which would be the address of eLandPtr? If someone could explain the process in English so I could get my head around it that would be great. It might be just because it has been a long day but its just not straight in my head at all.
Upvotes: 8
Views: 12136
Reputation: 12108
Here:
char eLangAr[20] = "English";
an array is created. It has capacity of 20 char
s and contains 8 characters - word "English" and terminating NULL character. Since it's an array, it can be used in a context where pointer is expected - thanks to array-to-pointer decay, which will construct a pointer to the first element of an array. This is done here:
char* eLangPtr = eLangAr;
Which is the same as:
char* eLangPtr = &eLangAr[0]; // explicitly get the address of the first element
Now, while char*
represents pointer to a character (which means it points to a single char
), the char**
represents a pointer to the char*
pointer.
The difference:
char text[] = "Text";
char* chPointer = &ch[0];
char** chPointerPointer = &chPointer; // get the address of the pointer
std::cout << chPointer; // prints the address of 'text' array
std::cout << *chPointer; // prints the first character in 'text' array ('T')
std::cout << chPointerPointer; // prints the address of 'chPointer'
std::cout << *chPointerPointer; // prints the value of 'chPointer' which is the address of 'text' array
std::cout << *(*chPointerPointer); // prints the first character in 'text' array ('T')
As you can see, it is simply an additional level of indirection.
Pointers to pointers are used for the same reason "first-level" pointers are used - they allow you to take the address of a pointer and pass it to a function which may write something to it, modifying the content of the original pointer.
In this case it is not needed, this would be sufficient:
const char *langStrings [3]=
{
eLangPtr,
fLangPtr,
gLangPtr
};
And then:
menu (langStrings[0]);
Upvotes: 0
Reputation: 25286
You are correct that langStrings
contains pointers to pointers of array of characters. So each langString[i]
points to a pointer. That pointer points to an array. That array contains the name of a language.
As others point out, it looks a bit clumsy. I'll elaborate:
char eLangAr[20] = "English";
is an array of 20 chars and the name "English
" is copied to it. I don't expect that variable eLangAr
will ever contain something else than this language name, so there is no need to use an array; a constant would be sufficient.
char **langStrings [3]= ...
Here, it would be sufficient to have just one indirection (one *) as there seems no need to ever have the pointer point to anything else (randomly shuffle languages?).
in conclusion, just having the following should be sufficient:
const char *langStrings [3]=
{
"English",
"French",
"German"
};
(Note the const
as the strings are now read-only constants/literals.)
char *langStrings [3]=
{
aLangArr,
fLangAr,
gLangAr
};
Upvotes: 8
Reputation: 1163
Ok, here goes. The **ptrToptr notation means a pointer to a pointer. The easiest way to think on that is as a 2D matrix - dereferencing one pointer resolves the whole matrix to just one line in the matrix. Dereferencing the second pointer after that will give one value in the matrix.
This declaration:
char eLangAr[20] = "English";
Declares an array of length 20, type char and it contains the characters 'E', 'n', 'g', 'l', 'i', 's', 'h' '\0' so it is (probably) null terminated but not full (there are some empty characters at the end). You can set a pointer to the start of it using:
char* englishPtr = &eLangAr[0]
And if you dereference englishPtr, it'll give the value 'E'. This pointer:
char* eLangPtr = eLangAr;
points to the array itself (not necessarily the first value).
If you look at
*langStrings[0]
You'll see it means the contents (the dereferencing *) of the pointer in langStrings[0]. langStrings[0] is the address of eLangPtr, so dereferencing it gives eLangPtr. And eLangPtr is the pointer to the array eLangAr (which contains "English").
I guess the function wants to be able to write to eLangAr, so make it point to a different word without overwriting "English" itself. It could just over-write the characters itself in memory, but I guess it wants to keep those words safe.
Upvotes: 1
Reputation: 49
** represents pointer to pointer. It's used when you have to store pointer for another pointer.
Value of eLangPtr will be pointer to eLangAr which will has the value "English"
Upvotes: 0