2

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.

Seoul
  • 585
  • 1
  • 4
  • 14
  • I have a suspicion about the validity of `g1` definition... – Eugene Sh. Jul 13 '17 at 19:30
  • 1
    g1 is a ```function that takes an int and returns a pointer to an array of size 10 chars``` – Seoul Jul 13 '17 at 19:32
  • 2
    Holly code... have never seen one like this and I don't want to see it again. So it is not preferred for me for sure. But probably good for some typechecking. – Eugene Sh. Jul 13 '17 at 19:33
  • 1
    Yes, I was just as shocked as you when I've found out about it! But it is valid so I need to know – Seoul Jul 13 '17 at 19:35
  • @Seoul _"But it is valid so I need to know"_ only for silly work interview I think. Completely useless in "normal" programming. Barely readable, easy to make silly mistakes. – 0___________ Jul 13 '17 at 20:05
  • 1
    "Is there a better way to write"? --> The cast in `return (void *)p;` is a hint that code is suspect. – chux - Reinstate Monica Jul 13 '17 at 21:12

3 Answers3

2

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;
}
  • 1
    `typedef char (*char_array_t)[10];` masks that the type is a pointer. See [Is it a good idea to typedef pointers?](https://stackoverflow.com/q/750178/2410359) – chux - Reinstate Monica Jul 13 '17 at 21:07
2

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 typedefs 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.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

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.

`

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256