I have the following function in C++ :
char** f()
{
char (*v)[10] = new char[5][10];
return v;
}
Visual studio 2008 says the following:
error C2440: 'return' : cannot convert from 'char (*)[10]' to 'char **'
What exactly should the return type to be, in order for this function to work?
char**
is not the same type as char (*)[10]
. Both of these are incompatible types and so char (*)[10]
cannot be implicitly converted to char**
. Hence the compilation error.
The return type of the function looks very ugly. You have to write it as:
char (*f())[10]
{
char (*v)[10] = new char[5][10];
return v;
}
Now it compiles.
Or you can use typedef
as:
typedef char carr[10];
carr* f()
{
char (*v)[10] = new char[5][10];
return v;
}
Ideone.
Basically, char (*v)[10]
defines a pointer to a char
array of size 10. It's the same as the following:
typedef char carr[10]; //carr is a char array of size 10
carr *v; //v is a pointer to array of size 10
So your code becomes equivalent to this:
carr* f()
{
carr *v = new carr[5];
return v;
}
cdecl.org
helps here:
char v[10]
reads as declare v as array 10 of char
char (*v)[10]
reads as declare v as pointer to array 10 of char
A pointer to pointers is not the same as a pointer to arrays.
(In particular, notice how sizeof(*ptr1)
is sizeof(char)*6
, whereas sizeof(*ptr3)
is sizeof(char*)
— this has serious ramifications for pointer arithmetic.)
new char[5][10]
gives you a char (*)[10]
(which has absolutely nothing to do with function pointers, by the way), because the pointers and chars are laid out in that fashion in memory (my second example).
This is not the same as char**
(which represents a different layout), so a conversion between the two makes no sense; hence, it is disallowed.
So your function's return type must be char (*)[10]
:
char (*f())[10] {
char (*v)[10] = new char[5][10];
return v;
}
Of course, this is really ugly, so you're far better off with a std::vector<std::string>
.
This FAQ entry explains it best, under the title "Conversions".
Because char**
and char (*)[10]
are two different types. char**
is a pointer to pointer(to char
), while char (*)[10]
is a pointer to an array(of size 10) of char
. Resultantly, the moving step of char**
is sizeof(void *)
bytes which is 4 bytes on win32 platform, and the moving step of char (*)[10]
is sizeof(char) * 10
bytes.
Example
char *c = NULL;
char **v = &c;
cout << typeid(v).name() << endl;
cout << (void*)v << endl;
v += 1;
cout << (void*)v << endl;
char d[10];
char (*u)[10] = &d;
cout << typeid(u).name() << endl;
cout << (void*)u << endl;
u += 1;
cout << (void*)u << endl;
Output
char * *
0034FB1C
0034FB20
char (*)[10]
001AFC50
001AFC5A
To use char (*)[10]
as a function's return type(or as input/output parameter of the function), the easiest and most readable way is to use a typedef
:
// read from inside-out: PTRTARR is a pointer, and, it points to an array, of chars.
typedef char (*PTRTARR)[10];
Note that it can easily be mixed up with typedef
of an array of pointers, if not careful:
// operator[] has higher precedence than operator*,
// PTRARR is an array of pointers to char.
typedef char *PTRARR[10];
Reference
Arrays and Pointers