7

I got confused by the accepted answer and the comments below it that are stating opposite things in Passing Arrays to Function in C++.

As formal parameter of a function is there any difference between passing an array as int arr[] or int arr[N]? In other words, is there a difference between void foo(int arr[]) and void foo(int arr[N])?

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 11
    The top answer says that they are equivalent to each other and to `int *`. That's the correct answer. – HolyBlackCat Dec 26 '19 at 17:44
  • 3
    You could get the answer yourself by taking the function declarations in your question and have the compiler attempt to distinguish between the two. `const int N = 10; void foo(int arr[]); void foo(int arr[N]);` You will see it [can't be done](http://coliru.stacked-crooked.com/a/d9efa8e0e0ed5c27) – PaulMcKenzie Dec 26 '19 at 17:45
  • 4
    The commentators didn't read the answer closely enough. The answer covers all the bases and the comments are irrelevant. – StoryTeller - Unslander Monica Dec 26 '19 at 17:45
  • If all you want is discriminate between different arguments, you must use a reference: `void f(int (&a)[4])` and `void f(int (&a)[8])` are different functions and must be called with arrays of specified size. – zdf Dec 26 '19 at 18:14
  • I have no idea why that comment on the top answer has so many votes. It is rude, and is just wasteful really. Even the article the commenter links to agrees with the actual answer! – ChrisMM Dec 26 '19 at 18:18
  • 1
    Use `std::array` or `std::vector` already. Forget that C-style arrays exist. – Jesper Juhl Dec 26 '19 at 18:19

1 Answers1

7

Both void foo(int arr[]) and void foo(int arr[N]) are exactly equivalent. This is because an array as an argument to a function is adjusted to a pointer. So both of the above translate to:

void foo(int *arr)

This is specified in section 6.7.6.3p7 of the C standard regarding "Function declarators":

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

Similar language exists in section 11.3.5p5 the C++ standard:

A single name can be used for several different functions in a single scope; this is function overloading(Clause 16). All declarations for a function shall agree exactly in both the return type and the parameter-type-list. The type of a function is determined using the following rules. The type of each parameter (including function parameter packs) is determined from its own decl-specifier-seq and declarator. After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T”. After producing the list of parameter types, any top-leve lcv-qualifiers modifying a parameter type are deleted when forming the function type. The resulting list of transformed parameter types and the presence or absence of the ellipsis or a function parameter pack is the function’s parameter-type-list.[Note:This transformation does not affect the types of the parameters.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    If `N` is an expression, more than just a simple constant, then the parameter declarations `int arr[]` and `int arr[N]` are not equivalent in C. In the latter, `N` is evaluated, even though the parameter type is adjusted to be `int *arr`. (I am not positive the C standard requires this, but it at least permits it, and both Clang and GCC do it.) For example, `#include ` / `static void foo(int a[printf("Hello\n")]) {} int main(void) { foo(0); }`, prints “Hello”. – Eric Postpischil Dec 26 '19 at 18:56
  • @EricPostpischil I never would have guessed that. I wonder why the grammar allows it? – dbush Dec 26 '19 at 20:07
  • 2
    It may be more bother than it is worth to change it, because you must allow size expressions in arrays not at the outermost level, as in `int a[][x]`, and those expressions must be evaluated so the called function knows the size. Excepting the outermost dimension might have been a nuisance to deal with in the grammar. Although there are some variations already; `int a[static 4]` in a parameter says `a` points to a place with at least 4 elements (and hence `a` cannot be a null pointer). – Eric Postpischil Dec 26 '19 at 20:11