12

As the title suggests, how to return pointer like this:

xxxxxxx foo() {

    static int arr[5][5];
    return arr;
}

BTW. I know that I must specify the size of one dimension at least, but how?

Determinant
  • 3,886
  • 7
  • 31
  • 47
  • A better question is _why_ you would want to return one. I honestly cannot think of any manner of program design where that makes sense. – Lundin May 29 '12 at 09:52
  • @Lundin Maybe a data-processing function which returns a pointer to a 2d array. – Determinant May 29 '12 at 13:56
  • That doesn't explain why you would need to return such a pointer, rather than use a pointer passed as one of the function's parameters, which is the convention in C. Returning pointers from functions is most often a clear indication of a bad program design. – Lundin May 30 '12 at 06:43
  • @Lundin You're right. I know it's very convenient to return multiple values using that method. But I think it's natural to return a pointer directly if there isn't any other return value. Why is that a bad program design? Can you explain it in detail? – Determinant May 30 '12 at 16:10
  • @Lundin well. Do you mean that the return value should be an error code instead of a pointer? – Determinant May 30 '12 at 16:12
  • Think of it: what could this pointer point at? It could point at a local variable (blatant bug), it could point at dynamic data (poor design), it could point at statics/globals (poor design and not thread-safe), or it could point at one of the passed parameters (pointless). – Lundin May 30 '12 at 19:11
  • @Lundin I know what you mean. Actually, I'm just writing a small program, which is an implementation of algorithm solving a problem. So it's clear that what this pointer is used for. – Determinant May 31 '12 at 15:31

2 Answers2

24

The return type would be int (*)[5] (pointer to 5-element array of int), as follows

int (*foo(void))[5]
{
  static int arr[5][5];
  ...
  return arr;
}

It breaks down as

      foo             -- foo
      foo(    )       -- is a function
      foo(void)       --   taking no parameters
     *foo(void)       -- returning a pointer
    (*foo(void))[5]   --   to a 5-element array       
int (*foo(void))[5]   --   of int

Remember that in most contexts, an expression of type "N-element array of T" is converted to type "pointer to T". The type of the expression arr is "5-element array of 5-element arrays of int", so it's converted to "pointer to 5-element array of int", or int (*)[5].

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 3
    Thank you for painting a thin layer of sanity on top of this atrocity that is C syntax. – Prof. Falken May 29 '12 at 12:00
  • 5
    C declaration syntax is actually fairly straightforward once you learn the basic rules. Ugly, but straightforward. If `(*a)[5]` is a pointer to an array, then `(*f())[5]` is a function returning a pointer to an array. – John Bode May 29 '12 at 13:32
  • Shouldn't it be `int (*foo(void))[5][5]`? – MustSeeMelons Sep 07 '22 at 13:51
  • 1
    @MustSeeMelons: That would be the case if we returned `&arr`, but we're not. The *expression* `arr` decays from type "5-element array of 5-element array of `int`" to "pointer to 5-element array of `int`". – John Bode Sep 07 '22 at 15:31
19

It helps to use a typedef for this:

typedef int MyArrayType[][5];

MyArrayType * foo(void)
{
    static int arr[5][5];
    return &arr;   // NB: return pointer to 2D array
}

If you don't want a use a typedef for some reason, or are just curious about what a naked version of the above function would look like, then the answer is this:

int (*foo(void))[][5]
{
    static int arr[5][5];
    return &arr;
}

Hopefully you can see why using a typedef is a good idea for such cases.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • maybe it would be `typedef int MyArrayType[5];` instead? – Determinant May 29 '12 at 07:44
  • @ymfoi: well, there is probably more than one way to do this - the above solution works for your specific question, but maybe you are trying to do something different than what you originally asked ? Do you want to return a pointer to a 2D array or not ? – Paul R May 29 '12 at 07:45
  • sorry, I just forgot to type &.. T T – Determinant May 29 '12 at 07:47
  • @PaulR can you tell me the expanded form of typedef? – Determinant May 29 '12 at 07:49
  • No problem - I should probably have highlighted this as it's easy to miss - I'll update the answer. – Paul R May 29 '12 at 07:49
  • @ymfoi: sorry - what do you mean by "expanded form" ? – Paul R May 29 '12 at 07:50
  • @PaulR I mean the form without `typedef`. – Determinant May 29 '12 at 07:56
  • 1
    OK - I have added a version without typedef above - please don't write code like this though ! – Paul R May 29 '12 at 08:16
  • No problem - for future reference http://cdecl.org/ is a very useful online version of the `cdecl` tool which translates C gibberish <-> English – Paul R May 29 '12 at 08:23
  • In C a function that takes no arguments should be declared with a void parameter list, e.g. `int foo(void)`. A function with *no* arguments, e.g. `int foo()`, is a function that can take *any number* of arguments. Do not use this form if you want your code to be robust. – Paul R May 29 '12 at 08:25
  • @PaulR Where can I find the standard which teaches me how to define some complex types? – Determinant May 29 '12 at 08:26
  • Read Kernighan & Ritchie: http://www.amazon.com/C-Programming-Language-2nd-Edition/dp/0131103628 and use the http://cdecl.org tool – Paul R May 29 '12 at 08:27
  • Oh, gotcha! To be honest, I'm writing c-style c++, do not aware of that. – Determinant May 29 '12 at 08:27
  • 2
    You need to be aware of the subtle but important differences between C and C++ - they are very different languages in many respects, but for basic POD types such as the above then you can mostly treat them as being similar. – Paul R May 29 '12 at 08:29
  • 1
    That is *HORRIBLE* type syntax. I thought I knew C. – Prof. Falken May 29 '12 at 11:59