简体   繁体   中英

C function declaration returning pointer to specific sized array

I have been playing around with C function declarations/definitions and came up with these.

Is there a reason why g1 would be preferred over g2 , other than wanting to return a pointer to a specific sized array?
Is there a better way to write g1 (with typedefs? etc.)?

#include <stdlib.h>

char (*g1(int dummy))[10]
{
 char (*p)[10] = malloc(sizeof *p);
 return p;
}

char * g2(int dummy)
{
 char (*p)[10] = malloc(sizeof *p);
 return (void *)p;
}

int main()
{
  g1(10);
  g2(20);
}

Thanks in advance.

From what I can tell, g1 returns a pointer to an array of char containing exactly 10 elements, whereas g2 returns a pointer to a single char , which would allow for a char array of any length following it in memory.

Seeing as C will not enforce the bounds of an array, the only advantage I can see with g1 over g2 is the ability to specify a size when assigning a variable, just as you have mentioned.

If you wanted to rewrite g1 using a typedef , you could use the following:

typedef char (*char_array_t)[10];

char_array_t g1(int dummy)
{
 char_array_t p = malloc(sizeof *p);
 return p;
}

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 (ie, 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 .

Is there a better way to write?

If the function needs to return "a pointer to an array of size 10 chars" then g1() is fine. It meets the design goal.

char (*g1(int dummy))[10] {
 char (*p)[10] = malloc(sizeof *p);
 return p;
}

If the function needs to return "a pointer to 10 chars" then use

char *allocate10char(int dummy) {
 char *p  = malloc(sizeof *p * 10);
 return p;
}

If char (*g1(int dummy))[10] is too strange, then the coding goal needs to imporve.

`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM