When passing an array as a parameter, this

void arraytest(int a[])

means exactly the same as

void arraytest(int *a)

so you are modifying the values in main.

Personally, I would use the second option, as it seems less confusing and better indicates that you don't get a copy of the array.

For historical reasons, arrays are not first class citizens and cannot be passed by value. Originally, C didn't have any pass by value, except for single values. It wasn't until struct was added to the language that this was changed. And then it was considered too late to change the rules for arrays. There were already 10's of users...

Answer from Bo Persson on Stack Overflow
Top answer
1 of 11
232

When passing an array as a parameter, this

void arraytest(int a[])

means exactly the same as

void arraytest(int *a)

so you are modifying the values in main.

Personally, I would use the second option, as it seems less confusing and better indicates that you don't get a copy of the array.

For historical reasons, arrays are not first class citizens and cannot be passed by value. Originally, C didn't have any pass by value, except for single values. It wasn't until struct was added to the language that this was changed. And then it was considered too late to change the rules for arrays. There were already 10's of users...

2 of 11
62

For passing 2D (or higher multidimensional) arrays instead, see my other answers here:

  1. How to pass a multidimensional [C-style] array to a function in C and C++, and here:
  2. How to pass a multidimensional array to a function in C++ only, via std::vector<std::vector<int>>&

Passing 1D arrays as function parameters in C (and C++)

1. Standard array usage in C with natural type decay (adjustment) from array to ptr

@Bo Persson correctly states in his great answer here:

When passing an array as a parameter, this

void arraytest(int a[])

means exactly the same as

void arraytest(int *a)

Let me add some comments to add clarity to those two code snippets:

// param is array of ints; the arg passed automatically "adjusts" (frequently said
// informally as "decays") from `int []` (array of ints) to `int *` 
// (ptr to int)
void arraytest(int a[])

// ptr to int
void arraytest(int *a)

However, let me add also that the above two forms also:

  1. mean exactly the same as

     // array of 0 ints; automatically adjusts (decays) from `int [0]`
     // (array of zero ints) to `int *` (ptr to int)
     void arraytest(int a[0])
    
  2. which means exactly the same as

     // array of 1 int; automatically adjusts (decays) from `int [1]`
     // (array of 1 int) to `int *` (ptr to int)
     void arraytest(int a[1])
    
  3. which means exactly the same as

     // array of 2 ints; automatically adjusts (decays) from `int [2]`
     // (array of 2 ints) to `int *` (ptr to int)
     void arraytest(int a[2])
    
  4. which means exactly the same as

     // array of 1000 ints; automatically adjusts (decays) from `int [1000]`
     // (array of 1000 ints) to `int *` (ptr to int)
     void arraytest(int a[1000])
    
  5. etc.

In every single one of the array examples above, and as shown in the example calls in the code just below, the input parameter type adjusts (decays) to an int *, and can be called with no warnings and no errors, even with build options -Wall -Wextra -Werror turned on (see my repo here for details on these 3 build options), like this:

int array1[2];
int * array2 = array1;

// works fine because `array1` automatically decays from an array type
// to a pointer type: `int *`
arraytest(array1);
// works fine because `array2` is already an `int *` 
arraytest(array2);

As a matter of fact, the "size" value ([0], [1], [2], [1000], etc.) inside the array parameter here is apparently just for aesthetic/self-documentation purposes, and can be any positive integer (size_t type I think) you want!

In practice, however, you should use it to specify the minimum size of the array you expect the function to receive, so that when writing code it's easy for you to track and verify. The MISRA-C-2012 standard (buy/download the 236-pg 2012-version PDF of the standard for £15.00 here) goes so far as to state (emphasis added):

Rule 17.5 The function argument corresponding to a parameter declared to have an array type shall have an appropriate number of elements.

...

If a parameter is declared as an array with a specified size, the corresponding argument in each function call should point into an object that has at least as many elements as the array.

...

The use of an array declarator for a function parameter specifies the function interface more clearly than using a pointer. The minimum number of elements expected by the function is explicitly stated, whereas this is not possible with a pointer.

In other words, they recommend using the explicit size format, even though the C standard technically doesn't enforce it--it at least helps clarify to you as a developer, and to others using the code, what size array the function is expecting you to pass in.


2. Forcing type safety on arrays in C

(Not recommended (correction: sometimes recommended, especially for fixed-size multi-dimensional arrays), but possible. See my brief argument against doing this at the end. Also, for my multi-dimensional-array [ex: 2D array] version of this, see my answer here.)

As @Winger Sendon points out in a comment below my answer, we can force C to treat an array type to be different based on the array size!

Quick summary

// `a_p` is a pointer to an array of 2 integers
int (*a_p)[2]; 

// Now, assuming you have this array of 2 integers:
int my_array[2];

// ...you can make `a_p` point to `my_array` like this:
a_p = &my_array;

// This, however, would be **illegal**, since `my_array2` is the wrong size
int my_array2[3]; // Ok: array of 3 `int`s
a_p = &my_array2; // ERROR! `a_p` is a ptr to an array of 2 ints, not 3 ints, 
                  //        so this assignment is not allowed!

Details

First, you must recognize that in my example just above, using the int array1[2]; like this: arraytest(array1); causes array1 to automatically decay into an int *. HOWEVER, if you take the address of array1 instead and call arraytest(&array1), you get completely different behavior! Now, it does NOT decay into an int *! This is because if you take the address of an array then you already have a pointer type, and pointer types do NOT adjust to other pointer types. Only array types adjust to pointer types. So instead, the type of &array1 is int (*)[2], which means "pointer to an array of size 2 of int", or "pointer to an array of size 2 of type int", or said also as "pointer to an array of 2 ints". So, you can FORCE C to check for type safety on an array by passing explicit pointers to arrays, like this:

// `a` is of type `int (*)[2]`, which means "pointer to array of 2 ints"; 
// since it is already a ptr, it can NOT automatically decay further
// to any other type of ptr 
void arraytest(int (*a)[2])
{
    // my function here
}

This syntax is hard to read, but similar to that of a function pointer. The online tool, cdecl, tells us that int (*a)[2] means: "declare a as pointer to array 2 of int" (pointer to array of 2 ints). Do NOT confuse this with the version withOUT parenthesis: int * a[2], which means: "declare a as array 2 of pointer to int" (AKA: array of 2 pointers to int, AKA: array of 2 int*s).

Now, this function REQUIRES you to call it with the address operator (&) like this, using as an input parameter a POINTER TO AN ARRAY OF THE CORRECT SIZE!:

int array1[2];

// ok, since the type of `array1` is `int (*)[2]` (ptr to array of 
// 2 ints)
arraytest(&array1); // you must use the & operator here to prevent
                    // `array1` from otherwise automatically decaying
                    // into `int *`, which is the WRONG input type here!

This, however, will produce a warning:

int array1[2];

// WARNING! Wrong type since the type of `array1` decays to `int *`:
//      main.c:32:15: warning: passing argument 1 of ‘arraytest’ from 
//      incompatible pointer type [-Wincompatible-pointer-types]                                                            
//      main.c:22:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
arraytest(array1); // (missing & operator)

You may test this code here.

To force the C compiler to turn this warning into an error, so that you MUST always call arraytest(&array1); using only an input array of the corrrect size and type (int array1[2]; in this case), add -Werror to your build options. If running the test code above on onlinegdb.com, do this by clicking the gear icon in the top-right and click on "Extra Compiler Flags" to type this option in. Now, this warning:

main.c:34:15: warning: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Wincompatible-pointer-types]                                                            
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’    

will turn into this build error:

main.c: In function ‘main’:
main.c:34:15: error: passing argument 1 of ‘arraytest’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     arraytest(array1); // warning!
               ^~~~~~
main.c:24:6: note: expected ‘int (*)[2]’ but argument is of type ‘int *’
 void arraytest(int (*a)[2])
      ^~~~~~~~~
cc1: all warnings being treated as errors

Note that you can also create "type safe" pointers to arrays of a given size, like this:

int array[2]; // variable `array` is of type `int [2]`, or "array of 2 ints"

// `array_p` is a "type safe" ptr to array of size 2 of int; ie: its type
// is `int (*)[2]`, which can also be stated: "ptr to array of 2 ints"
int (*array_p)[2] = &array;

...but I do NOT necessarily recommend this (using these "type safe" arrays in C), as it reminds me a lot of the C++ antics used to force type safety everywhere, at the exceptionally high cost of language syntax complexity, verbosity, and difficulty architecting code, and which I dislike and have ranted about many times before (ex: see "My Thoughts on C++" here).


For additional tests and experimentation, see also the link just below.

References

See links above. Also:

  1. My code experimentation online: https://onlinegdb.com/B1RsrBDFD

See also:

  1. My answer on multi-dimensional arrays (ex: 2D arrays) which expounds upon the above, and uses the "type safety" approach for multi-dimensional arrays where it makes sense: Why can't I pass a C-style multidimensional array to a function taking an array of int*?
  2. C pointers : pointing to an array of fixed size
🌐
Programiz
programiz.com › c-programming › c-arrays-functions
Pass arrays to a function in C
Here, we have passed array parameters to the display() function in the same way we pass variables to a function. // pass second and third elements to display() display(ageArray[1], ageArray[2]); We can see this in the function definition, where the function parameters are individual variables:
Discussions

When passing an array to a function, do you always have to pass the length as well?
As I understand it, int *A is the same as int A[] because everything is passed by reference, correct? Quite the opposite in fact: everything is passed by value, but you pass the value of the pointer to the first element of the array. So yes, you have to pass the length. Also, sizeof(A)/sizeof(int))\ is better written as: sizeof(A)/sizeof(*A) (so you don't have to duplicate the type). More on reddit.com
🌐 r/C_Programming
31
35
May 1, 2022
Passing array to function: different ways
test1 is taking an array of int pointers. Each of these pointers point to the individual elements of arr1, where those are dereferenced to get to the value of each element of arr1. I hazard a guess that this line of approach was not your intent or expectation based on your line of questioning. If so, avoid this approach. However, it is important to understand what is going on, so make sure you follow the logic. More on reddit.com
🌐 r/C_Programming
7
2
January 7, 2022
Passing arrays to function in C - Stack Overflow
I just want to know why, when I pass arrays to functions, say, for example, to initialize them, they actually initialize. Since the variables in the inic function are completely independent from th... More on stackoverflow.com
🌐 stackoverflow.com
history - Why can't arrays be passed as function arguments in C? - Software Engineering Stack Exchange
I am not sure it is the answer, but part of the type of an array is its size, so I believe you would have to define a function for every size you want to accept. ... Do you mean as function pointers? Please clarify the question. ... @user949300 No, from the context of the comment it's pretty clear; you can't pass ... More on softwareengineering.stackexchange.com
🌐 softwareengineering.stackexchange.com
June 20, 2014
🌐
TutorialsPoint
tutorialspoint.com › cprogramming › c_passing_arrays_to_functions.htm
Passing Arrays as Function Arguments in C
C - Pointers vs. Multi-dimensional Arrays ... If you want to pass an array to a function, you can use either call by value or call by reference method. In call by value method, the argument to the function should be an initialized array, or ...
🌐
Scaler
scaler.com › home › topics › pass array to function in c
Passing Array to Function in C - Scaler Topics
April 25, 2024 - Because we have passed array by reference changes on array persists when program leaves the scope of the function. We can return an array from function in C using four ways ... For first three cases we can return the array by returning poiniter pointing to base address of the array.
🌐
Reddit
reddit.com › r/c_programming › when passing an array to a function, do you always have to pass the length as well?
r/C_Programming on Reddit: When passing an array to a function, do you always have to pass the length as well?
May 1, 2022 -

Let's say I have the following function:

int maxSubArray(const int *A, const int len) {
    int currentMax = 0;
    int overallMax = 0;
    for (int i = 0; i < len; ++i) {
        currentMax = (currentMax + A[i] > 0) ? currentMax + A[i] : 0;
        if (currentMax > overallMax) overallMax = currentMax;
    }
    return overallMax;
}

I would have to call maxSubArray(A, sizeof(A)/sizeof(int)).

As I understand it, int *A is the same as int A[] because everything is passed by reference, correct?

So is there even a way to reduce the signature to int maxSubArray(const int *A)? Or do you just have to pass the length as argument when you need it in C?

🌐
BeginnersBook
beginnersbook.com › 2014 › 01 › c-passing-array-to-function-example
Passing array to function in C programming with example
September 24, 2017 - When we pass an address as an argument, the function declaration should have a pointer as a parameter to receive the passed address. #include <stdio.h> void disp( int *num) { printf("%d ", *num); } int main() { int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; for (int i=0; i<10; i++) { /* Passing ...
Find elsewhere
🌐
Medium
medium.com › @techactive6 › passing-arrays-to-function-in-c-c2f6c07a68e2
Passing Arrays to Function in C. Like the values of simple variables, it… | by Pedagogy Zone | Medium
June 1, 2021 - for example, the call largest(a,n) will pass the whole array a to the called function. The called function expection this call must be appropriately defined. The largest function header might look like: float largest(float array[], int size) ...
🌐
Sankalandtech
sankalandtech.com › Tutorials › C › passing-array-function-c.html
Passing an array to Function in C Programming.
Next the the printf("\n Array ... shows the output "Sum of array elements=16693" Passing the actual value of variable into function is known as "Passing by value" ....
🌐
Tutorial Gateway
tutorialgateway.org › pass-array-to-functions-in-c
Pass Array to Functions in C
March 24, 2025 - Within the main program, we used for loop to iterate the array and pass each element to the function that we created earlier. #include<stdio.h> void PrintArray(int a) { printf("Item = %d \n", a); } int main() { int array[] = {1, 2, 3, 4, 5, 6}; for (int i = 0; i < 6; i++) { PrintArray(array[i]); } return 0; }
🌐
Reddit
reddit.com › r/c_programming › passing array to function: different ways
r/C_Programming on Reddit: Passing array to function: different ways
January 7, 2022 -

Hi all,

at the moment I am failing in getting the right way of doing the following.

As I understand, on the call of test, the start address of the array is passed as the first argument. But a call like test(&arr[0], size); will also work.

In test1, the whole pointer is passed as an argument to the function, isn't it?

So my question are, which is the right way doing this?

  1. like test is called

  2. call test like this test(&arr[0], size);

  3. or like test1 is called?

Further: Why does test1 only work if there is *p[i] = i; and not p[i] = i; like in test?

And are there any dis- or advantages when doing the one or the other?

Thanks and cheers, noob

#include <stdio.h>


void test(int* p, int size)
{
  for (int i = 0; i < size; i++) {
    p[i] = i;
  }
}

void test1(int* p[], int size)
{
  for (int i = 0; i < size; i++) {
    *p[i] = i;
  }
}

int main()
{
  const int size = 5;
  
  int arr[size];
  int arr1[size];
  int* p1[size];

  for (int i = 0; i < size; i++) {
    arr[i] = 0;
    arr1[i] = 0;
    p1[i] = &arr1[i];
  }
  
  test(arr, size);
  for (int i = 0; i < size; i++) {
    printf("test: %d\n", arr[i]);
  }

  test1(p1, size);
  for (int i = 0; i < size; i++) {
    printf("test1: %d\n", arr1[i]);
  }

  return 0;
}
🌐
Codeforwin
codeforwin.org › home › how to pass and return array from function in c?
How to pass and return array from function in C? - Codeforwin
July 20, 2025 - To overcome this you can either allocate array dynamically using malloc() function. Or declare array within function as static variable. Or you can pass the array to be returned as a parameter to the function.
🌐
Linux Hint
linuxhint.com › pass-array-function-c
Passing array to function in C – Linux Hint
If you need to keep comparable elements, a C array is useful. There are a variety of general situations in C that need sending several variables of the identical type to a function. Assume a function that arranges the 30 elements in ascending order; the real parameters from its main function must be passed as 30 numbers to this function.
Top answer
1 of 4
21

My first guess for the reason was simply because of performance and memory saving reasons, and for the ease of compiler implementation as well (especially for the kind of computers at the time when C was invented). Passing huge arrays "by value" seemed to have a huge impact at the stack, it needs a full array copy operation for each function call, and probably the compiler must be smarter to output the correct assembly code (though the last point is debatable). It would also be more difficult to treat dynamically allocated arrays the same way as statically allocated arrays (from the viewpoint of the language's syntax).

EDIT: after reading some parts from this link, I think the real reason (and the reason why arrays in structs are treated as value types, while sole arrays are not) is the backward compatibility to C's predecessor B. Here is the cite from Dennis Ritchie:

[...} The solution constituted the crucial jump in the evolutionary chain between typeless BCPL and typed C. It eliminated the materialization of the pointer in storage, and instead caused the creation of the pointer when the array name is mentioned in an expression. The rule, which survives in today's C, is that values of array type are converted, when they appear in expressions, into pointers to the first of the objects making up the array.

This invention enabled most existing B code to continue to work, despite the underlying shift in the language's semantics. [..]

2 of 4
9

A PDP minicomputer with only 8 kB of memory can't allocate a very large stack. So, on such a machine, one has to be careful in a language design (or evolution) to be able to minimize what needs to go on the stack for expected common subroutine call usage. C is still used today to program extremely memory constrained (a few kB) embedded systems, so the trade-off is usually a good one.

On a processor architecture which has very few registers, passing any array by pointer rather than by value more often allows a register to be used as a subroutine call optimization.

🌐
Arduino Forum
forum.arduino.cc › projects › programming
Passing Array to Function in C/CPP - Programming - Arduino Forum
October 1, 2021 - Wanted to know what are the methods that I can follow to pass an array to function in C and CPP. Any suggestions would be helpful for me to understand.
🌐
guvi.in
studytonight.com › c › array-in-function-in-c.php
Passing Arrays to Functions in C
September 17, 2024 - We don't return an array from functions, rather we return a pointer holding the base address of the array to be returned. But we must, make sure that the array exists after the function ends i.e. the array is not local to the function.