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.

6
  • I have a suspicion about the validity of g1 definition... Commented Jul 13, 2017 at 19:30
  • 1
    g1 is a function that takes an int and returns a pointer to an array of size 10 chars Commented Jul 13, 2017 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. Commented Jul 13, 2017 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 Commented Jul 13, 2017 at 19:35
  • 1
    "Is there a better way to write"? --> The cast in return (void *)p; is a hint that code is suspect. Commented Jul 13, 2017 at 21:12

3 Answers 3

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

typedef char (*char_array_t)[10]; masks that the type is a pointer. See Is it a good idea to typedef pointers?
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.

2 Comments

UV for good answer (except that 2D part - no 2D array in code).
@chux: mine or the OP's? No, the OP didn't create a 2D array, but IME there's almost never a reason to create a pointer to an array unless you're allocating a multi-dimensional array.
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.

`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.