0

I'm curious if I give an n-dimensional array for n>1 as an argument to a function, are the contents of whole array copied or just the pointer to the address of the first element.

Assume function signature is something like this:

int someFunction(int n, int arr[n][n]);
Behlül
  • 3,412
  • 2
  • 29
  • 46
  • 3
    This is something that you could (a) easily try out and (b) do a little web searching for (e.g. http://c-faq.com/aryptr/). – Oliver Charlesworth Mar 28 '13 at 17:40
  • What do you mean by "array copied?" Nothing is copied on a function call. Just a pointer being passed in. – OldProgrammer Mar 28 '13 at 17:42
  • @LeorA - think again (what if an `struct` is passed) – Kiril Kirov Mar 28 '13 at 17:43
  • @OliCharlesworth: C doesn't have multidimensional arrays as part of the langauge. It has arrays of arrays (and arrays of pointers to arrays) neither of which is quite a proper multidimensional array, though either can be used as such in some contexts. – Chris Dodd Mar 28 '13 at 17:44
  • 1
    @ChrisDodd: How would you distinguish "multidimensional array" from "array of arrays"? (Also note that the phrase "multidimensional array" is indeed used in the language standard...) – Oliver Charlesworth Mar 28 '13 at 17:45
  • @OliCharlesworth: A proper multidimensional array would support things like transposing dimensions and slicing. C does not. – Chris Dodd Mar 28 '13 at 17:49
  • 1
    @ChrisDodd: I'm not sure that's intrinsic to the definition; that's just functionality. It doesn't have slicing for 1D arrays either... – Oliver Charlesworth Mar 28 '13 at 17:50
  • @OliCharlesworth: You can extract a slice from a 1D array with pointer addition. But yes, C arrays aren't really fully arrays either, as they magically turn into pointers in many contexts, leading to confusion for new programmers – Chris Dodd Mar 28 '13 at 17:52
  • @ChrisDodd: Well, that's essentially true for 2D arrays too (it's just a little more complicated ;) ). Anyway, I fear we may be straying from the question topic... – Oliver Charlesworth Mar 28 '13 at 17:55

2 Answers2

4

[Where I just re-learned this yesterday]

This is a C99 extension that is not widely known. The array is still passed by reference as they always have been, but the compiler is able to interpret it as an array similar to the way it handles Variable-Length Arrays.

This won't give you bound-checking, of course. C doesn't have that.

In your function signature,

int someFunction(int n, int arr[n][n]);

The final n doesn't really buy you anything, it just gets ignored. But int arr[n][] is new. That's what C89 didn't have. Previously, the only option was to calculate indices manually off of the base pointer, arr[n*x+y].

In Ansi-C (C89), you'd have to declare the function as,

int someFunction(int n, int arr[]);

which is equivalent to

int someFunction(int n, int *arr);

and calculate the two dimensions as a single index.

The new C99 magic, reduces the original to this:

int someFunction(int n, int *arr[n]);

I'd describe the process more as array adoption, than passing. It just mitigates some of the losses that were incurred by the original decision to pass arrays as pointers.


It's important to understand that second two examples are sort-of internalized equivalents. Figurative illustrations. In the final one, the array is not converted into an array of pointers, but the bounds of the lowest dimension is dropped. Perhaps it's better illustrated like this:

int someFunction(int n, int arr[n][]);

The only way to copy an array as a function argument is to wrap it in a struct. But then you cannot have variable dimensions.

struct arr {int n; int arr[n][n];}; //Nope, won't compile!

enum { n = 3 };
struct arr { int arr[n][n]; };

struct arr someFunction( struct arr ); //argument and return value are copied.

And this has been legal since 1989.

Community
  • 1
  • 1
luser droog
  • 18,988
  • 3
  • 53
  • 105
  • Thanks, details in different versions of C are always confusing :) – Behlül Mar 28 '13 at 17:55
  • 2
    `int someFunction(int n, int arr[][]);` is invalid C. And an array of pointers as you have in your last examples is different from a multidimensional array. – interjay Mar 28 '13 at 17:55
  • Thanks. I think I got confused by reading too much on tuhs.org. There are primitive versions which *do* accept that syntax. – luser droog Mar 28 '13 at 18:01
-1

That's an illegal signature for a function, as arrays in function signatures must have constant dimensions (other than the final dimension).

The reason that arrays must have constant sizes as function parameters is because they aren't actually copied in the function call -- only a pointer is passed.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • 1
    I would be inclined to agree… but GCC and Clang will both happily compile a function with that signature! –  Mar 28 '13 at 17:42
  • 2
    This is valid in C99, I believe... (see the examples in section 6.7.5.3) – Oliver Charlesworth Mar 28 '13 at 17:43
  • 1
    Besides this answer being based on a false premise, I also don't see why you think that an array having a constant size has anything to do with whether it is copied or not. – interjay Mar 28 '13 at 17:48
  • It is correct per C89, and covers the rationale behind not allowing unspecified sizes on array dimensions other than the last one. – Chris Dodd Mar 28 '13 at 18:01