You are both correct. :-]
If you want to be really technical, you are returning a pointer to a pointer to a
char. C++ allows you to treat pointers as arrays, because:
a[ n ]
is really shorthand for
*(a + n)
Therefore, it follows that a pointer to data can be treated as an array of data.
This leads to an interesting feature of the language: a 2D array can be physically represented in two different ways.
But before we get that far, remember that in C there really is no such thing as a multidimensional array... only the
appearance of one. All arrays are actually linear.
The first representation of a 2D array is just some funky indexing of a linear array.
1 2 3 4 5 6 7 8 9 10 11
|
// This creates a ONE-dimensional array of integers
// that are indexed as if it were a TWO-dimensional array.
int a[ 10 ][ 20 ];
// But we can still treat it as a one-dimensional array.
int* b = a;
// Each of the following statements do exactly the same thing
a[ 5 ][ 7 ] = 42;
*(b + (5 * 20) + 7) = 42;
*(b + 107) = 42;
| |
In fact, the first statement is, again, a convenience for us programmers. The compiler will convert it into the second if any of the indices are variable, or the third if all indices are constant (as they are in the example).
The second representation capitalizes on the "pointer is an array" feature of the language in a different way, and adds a new power to arrays that the first method lacks: variably-dimensioned subscripts. For example:
1 2 3 4 5 6 7 8
|
const char* names[ 5 ] =
{
"Anne",
"Courtney",
"Nuala",
"Seanaed",
"Tera"
};
| |
In this case, the array
names is really an array of
const char* (like it says it is), but what if I had written the declaration as:
const char** names =
It is technically correct. The compiler will prevent it in order to keep the programmer from shooting himself in the foot, but you can use the construct in a function's argument list and pass
names to the function -- where the compiler forgets all dimensional information about the original array. (That's why we pass the size of an array to functions also... since we can't rely on the compiler to give us information about the original array from a function.)
Using the array is exactly the same: to access the third letter of the second name we write:
cout << names[ 1 ][ 2 ] << endl;
Remembering that we just used some fancy syntax magic to do something simpler with pointers, we can rewrite it as:
cout << *(*(names + 1) + 2) << endl;
In other words, we first dereference the outer dimension
char* inner_char_pointer = *(names + 1);
to find the inner array's char pointer, then we dereference
that pointer to get the character desired.
char c = *(inner_char_pointer + 2);
So, to keep your boss happy, you might want to be explicit about the way the 2D array is stored:
1 2 3 4
|
returns
NULL on failure.
Else a pointer to an array of (char*). Each sub-array of characters represents ...
All data is allocated on the heap using malloc().
| |
Hope this helps.