g1
is more "correct" since it accurately reflects the type of the object you are returning (pointer to 10-element array of char
). You don't normally see functions that return pointers to arrays, since the array size must be fixed at compile time, limiting its usefulness, and most of us subconsciously avoid writing code like that because it's just too damned eye-stabby. If I were writing a function that allocated a 2D array, I'd usually write it as
void g1( size_t rows, size_t cols, char (**p)[cols] )
{
*p = malloc( sizeof **p * rows );
}
int main( void )
{
char (*table)[10];
g1( 5, 10, &table );
if ( table )
{
...
}
}
which allows me to take advantage of VLA semantics (in C99 or later), making it flexible without being excessively ugly.
You can typedef some of the ugliness away:
typedef char MyType[10];
MyType *g1( int dummy );
{
MyType *p = malloc( sizeof *p );
...
return p;
}
but I'm leary of using typedef
s just to make the code scan better. You should only typedef
a type for abstraction purposes (i.e., to hide the implementation from the user of the type). If the user of the type needs to be aware of the "array-ness" of the type, then do not hide it behind a typedef
.
I don't like g2
because it lies. p
is not a char *
, it's a char (*)[10]
. That matters.