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.