How to pass an array to a function in C++
In C++, arrays are derived data types that store multiple values of the same type under a single name. When you pass an array to a function, the array name decays to a pointer to its first element, meaning the function receives a memory address rather than a copy of the entire array. This is why you should always pass the array size as a separate parameter and use const when the function only needs read access.
Learning outcomes
Declaration and initialization: One-dimensional arrays use the syntax
DataType Name[Size], while two-dimensional arrays add a second bracket for rows and columns, and both can be declared and initialized in a single step.Passing to functions: You pass an array by specifying its type and name with square brackets in the function signature, and you should always include the array size as an additional parameter to avoid out-of-bounds access.
Pointer decay and sizeof pitfalls: Arrays decay to pointers inside function parameters, so
sizeof(arr)returns the pointer size rather than the full array size, which is a common source of bugs.Modern alternatives: C++20's
std::spancarries both a pointer and a length to prevent decay issues, whilestd::vectorandstd::arrayoffer safer memory management through RAII.Returning array-like results: You cannot return a raw C-style array from a function, but you can return a
std::vector, astd::array, or a heap-allocated pointer with a clear ownership contract.
Arrays are useful data types for data structures in C++ programming and beyond. In simple terms, arrays allow you to store data as an ordered list. You can use arrays to easily sort or calculate information about a collection of data using a single array name.
Today, we’ll discuss how to pass arrays to functions in C++. Along the way, we’ll cover why we use C++ arrays, as well as how to declare and initialize them. We’ll then pass them to functions and discuss important distinctions about arrays in C++. This article includes tutorials for both one-dimensional and two-dimensional arrays.
Get hands-on with C++ today.
C++ is a popular language used to develop browsers, games, and operating systems. It's also an essential tool in the development of modern technology like IoT and self-driving cars. This Path will expand your knowledge of C++ with lessons built for professional developers. This Path will take you from basic to advanced concepts with hands-on practice. By the end, you'll have enough C++ experience to confidently solve real-world problems.
Arrays and data structures in C++#
Arrays are part of a bigger concept in computer science: data structures. We use data structures to organize and store data in order to efficiently perform operations on that data. Data structures are composed of smaller components called data types. Arrays are a data type frequently used in data structures.
As illustrated in the diagram, C++ has the following data types:
Primitive (or fundamental) data types
Derived data types
User-defined data types
Arrays are derived data types. Derived data types are composed of primitive or built-in data types. Derived data types have some of the abilities that primitive data types lack. For instance, primitive data types can’t store more than one value at a time, while arrays can.
Arrays allow you to store and access multiple values of the same data type under a single name. Arrays are useful when you’re dealing with a large amount of data. For instance, given data on 100 students and their grades, it would be tedious to declare 100 variables to store each student’s grade. Instead, we’d use an array to store all the data under a single name.
Basic terms associated with arrays are elements of the array, index of the array, and size of the array.
Element: Refers to values stored in an array (at neighboring memory locations)
Index: Refers to an array element’s position, starting from 0 and increasing incrementally by one for each additional element
Size: Refers to the total number of elements stored in an array
Here’s an illustration of an array with six elements. The array size is six according to the number of elements. Each of the six elements are stored at their respective indexes (e.g. the first element of the array, 10, is stored in index zero).
A two-dimensional array (or 2-d array) is an array of arrays. Two-dimensional arrays represent a matrix. They are the most commonly used multidimensional arrays. We can access the elements in a two-dimensional array by specifying their row and column index, which start at zero and increase incrementally with each added element.
This matrix illustration represents an array of size nine. Each of the nine elements are stored at a respective row and column index.
A pointer is another derived data type that’s relevant to today’s discussion. We’ll discuss more about pointers toward the end of this article.
Array declaration in C++#
How to declare a one-dimensional array#
The general syntax for declaring a one-dimensional array involves specifying the data type, name of the array, and size of the array:
In this code, we declare a one-dimensional array Roll_Number that can store five integer values. The compiler reserves space for five elements of int data type consecutively in memory.
How to declare a two-dimensional array#
The general syntax for declaring a two-dimensional array involves specifying the data type, array name, row index, and column index:
In this code, we declare a two-dimensional array Student[10][5] that can hold 10 arrays of Student[5]. Each Student[5] array can store five integer values. The compiler reserves space for 50 elements (10*5) of the int data type consecutively in memory.
How to initialize a two-dimensional array#
The general syntax for initializing a two-dimensional array is:
This code initializes a two-dimensional array that stores: 100 at row index 0 and column index 0, 134 at row index 0 and column index 1, and so on.
How to declare and initialize two-dimensional arrays#
The general syntax to initialize and declare a two-dimensional array is:
In this example, we initialize the Student[][3] array in the declaration step. Specifying the first dimension is optional when initializing two-dimensional arrays. The compiler will infer the number of rows from your statement. That’s why the code in this example is written with Student[][3] instead of Student[3][3].
Real-world example: Building a student grade analytics system#
Learning how to pass arrays to functions is easier when you see how the technique is used in a real application. In practice, programs rarely work with a single value at a time. Instead, they process collections of related data, such as student grades, sales figures, sensor readings, or user activity logs.
Imagine a school that wants a program to analyze the grades of hundreds of students and generate classroom statistics. Rather than storing each grade in a separate variable, the program stores all grades in an array and passes that array to different functions that perform specific tasks. This approach keeps the code organized, efficient, and easy to maintain as the system grows.
Project overview#
Suppose our school system needs to answer questions such as:
What is the class average?
What is the highest score?
How many students passed?
How does each student perform across multiple assignments?
Instead of writing separate code for every calculation, we can create reusable functions that operate on the same dataset.
The data#
The program starts by storing student grades in a one-dimensional array:
int grades[] = {92, 85, 78, 96, 88, 91, 73, 84};
This array represents the scores of eight students. Rather than duplicating data across multiple functions, we can pass the array as an argument whenever we need to analyze it.
The result is a cleaner design where each function focuses on a single responsibility while sharing access to the same collection of grades.
Calculating the class average#
One common requirement is calculating the average score across the entire class.
double calculateAverage(const int grades[], int size) {int total = 0;for (int i = 0; i < size; i++) {total += grades[i];}return static_cast<double>(total) / size;}
This function accepts two parameters:
The array containing student grades
The number of elements in the array
Notice the use of const. Since the function only reads the grades and does not modify them, const helps prevent accidental changes and clearly communicates the function's intent.
Passing the array allows the function to work with any class size without creating a copy of the data.
Finding the highest score#
Schools often want to identify top-performing students.
int findHighestScore(const int grades[], int size) {int highest = grades[0];for (int i = 1; i < size; i++) {if (grades[i] > highest) {highest = grades[i];}}return highest;}
This function reuses the same array but performs a completely different analysis.
One of the major benefits of passing arrays to functions is that multiple operations can work on the same dataset efficiently. The program doesn't need separate storage for averages, rankings, and reports—it simply passes the array wherever it's needed.
Counting passing students#
Another useful report is determining how many students passed the course.
int countPassingStudents(const int grades[], int size) {int passingCount = 0;for (int i = 0; i < size; i++) {if (grades[i] >= 70) {passingCount++;}}return passingCount;}
This function demonstrates how arrays make bulk processing straightforward. Whether the class contains eight students or eight hundred, the same logic applies.
The function receives the collection of grades and evaluates each score using a simple rule. Because arrays store related values together, operations like counting, searching, and filtering become efficient and easy to implement.
Extending the system with two-dimensional arrays#
As requirements grow, schools often need to track multiple assignments for each student.
A two-dimensional array can represent an entire gradebook:
int grades[3][4] = {{90, 85, 88, 92},{78, 80, 75, 82},{95, 93, 97, 96}};
In this example:
Rows represent students
Columns represent assignments
A reporting function might accept the gradebook and calculate averages, assignment statistics, or student performance summaries.
void generateReport(const int grades[][4], int students) {// Process gradebook data}
This design allows the program to analyze classroom performance while keeping the data organized in a structured format.
Why passing arrays matters#
It's easy to underestimate the value of passing arrays until you compare it with the alternative.
Without arrays:
int student1 = 92;int student2 = 85;int student3 = 78;// Hundreds more variables...
Every new student requires another variable, and every function would need a long list of parameters.
With arrays:
int grades[] = {92, 85, 78, 96, 88, 91, 73, 84};
The benefits are immediate:
One collection stores all related values.
Functions become reusable.
Code is easier to read and maintain.
Programs scale naturally as datasets grow.
This efficiency is possible because arrays are passed by pointer decay in traditional C++. Instead of copying every element, the function receives access to the existing memory location. Modern alternatives such as std::span, std::vector, and std::array build on the same idea while providing additional safety and convenience.
Lessons learned#
This student grade analytics system demonstrates a common pattern found throughout software development: store related data in collections and pass those collections to specialized functions for processing.
The same approach appears in business dashboards analyzing sales data, scientific applications processing measurements, financial systems evaluating transactions, and recommendation engines examining user activity. Rather than working with individual values, these systems operate on large datasets using reusable functions.
Understanding how arrays are passed to functions in C++ is an important step toward building larger, more maintainable applications. It teaches not only the mechanics of parameter passing but also the broader principle of organizing data so that multiple parts of a program can work together efficiently.
Passing arrays to functions in C++#
Now that we’ve covered the basics, let’s start passing arrays to C++ functions. We can use array names as parameters during function declaration.
To pass arrays to a function, we specify the array type, followed by the name of the array and square brackets in the function parameters. The square brackets tell the compiler that the first function parameter is an array, otherwise, a variable will be assumed.
Passing one-dimensional arrays to functions#
The general syntax for passing an array to a function in C++ is:
In this example, our program will traverse the array elements. We’ll modify the value of any element less than 50 to a value of -1.
Passing array along with its size (safe parameterization)#
When you pass an array to a function in C++, it’s almost always necessary to also pass the size (or length) of the array so the function knows how many elements it can safely access. A common pattern:
void process(int arr[], int n) {for (int i = 0; i < n; ++i) {// safe access arr[i]}}
Call it like:
int data[5] = {1, 2, 3, 4, 5};process(data, 5);
Alternatively:
void process(int *arr, size_t n);
Note: inside process, sizeof(arr) will not yield the full array size because arr decays to a pointer. That’s why passing explicit n is essential. Many bugs arise when code assumes a global constant size or miscalculates bounds.
Using const and read-only arrays#
When a function does not need to modify the array, express that intention using const. This helps with safety and clarity:
void print(const int arr[], int n) {for (int i = 0; i < n; ++i) {std::cout << arr[i] << " ";}}
Because arr is const, any attempt to write arr[i] = 5; will be a compile error. If you’re passing an entire buffer for read-only purposes, this is best practice when using pass array to function in C++.
You can also use:
void print(const int *arr, size_t n);
Or:
void print(const int arr[/*n*/], size_t n);
All three are equivalent in meaning thanks to pointer decay, but including const is a strong documentation aid.
Passing two-dimensional arrays to functions#
In this example, we’ll pass the two-dimensional array int n[][2] to a function we define as display() and print the array’s elements. For the function call, we only pass the array’s name as the function argument display(num).
Dynamic and jagged arrays, vectors, and std::array#
Static arrays suffer from fixed size limitations. In modern C++ development, you’ll often use:
Dynamic 2D arrays (pointer of pointers):
std::vector<vector<int>>or flatvector<int>with stride:std::array<T, N>: a fixed-size array that behaves like a value object:
int **grid = new int*[rows];for (int i = 0; i < rows; ++i)grid[i] = new int[cols];// pass grid and sizesvoid process(int** arr, int r, int c);
void process(const std::vector<std::vector<int>>& mat);
void f(std::array<int, 5> arr);
When you use these modern container types, you shift from raw pointer arithmetic and make your code safer and more idiomatic. They also integrate well with memory management and RAII.
Arrays: Pointers and passing by reference#
You may have noticed that we didn’t specify the size of the array when passing them to functions. The reason for this has to do with the fact that, by default, arrays are passed by reference to arguments. This is different from the case for variables, which are passed by value. When we use an array name as a function parameter, we’re actually passing the original array to the function. Let’s expand on exactly what that means.
Arrays are passed by reference for practical reasons. For instance, imagine we had a large array with a size of 10,000. It would be taxing to pass the entire array and its 10,000 elements. In fact, we actually can’t pass an entire array to a function in C++. Under the hood, what we’ve been doing all along is passing a pointer, which contains a memory address to the first element of the array.
We mentioned pointers earlier as another derived data type. Pointers hold memory addresses of other data types. When we use a pointer type as a function parameter instead of a data value, we’re giving the function a memory address directly to the specific piece of data. For objects that are passed by reference to a function, any change to the formal function parameter affects the actual parameter in the calling environment. This is because the formal parameter receives a reference (or pointer) to the actual data.
In C++, you technically get a pointer with every array declaration. Arrays and pointers are not equivalent, but their arithmetic is defined such that a pointer can serve to access or simulate an array. The name of the array acts as a pointer to the memory address of the array’s first element. When an array appears in an expression, the compiler generates a pointer to the address of the first element of the array.
Array decay, sizeof pitfalls, and std::span#
One of the trickiest things when you pass array to function in C++ is that arrays decay to pointers in function parameters. That means:
void foo(int arr[]) { /* arr is really int* */ }
Inside foo, sizeof(arr) gives the size of a pointer, not the size of the whole array. A common mistake:
int data[10];foo(data);// inside foo, sizeof(arr) / sizeof(arr[0]) == sizeof(int*) / sizeof(int) — wrong!
To counter this, modern C++ (C++20) introduces std::span<T> (or other “view” types). A span is a lightweight view that carries a pointer + length:
void process(std::span<int> arr) {for (int x : arr) {// use x}}
int data[5];process(data); // deduces span size automatically
std::span prevents the sizeof trap and makes slicing/viewing arrays safer. It’s a good tool to teach alongside the classic if you want your tutorial on pass array to function in C++ to be forward-looking.
Returning arrays or array-like results from functions#
Sometimes you want a function not just to consume but to produce an array-like result. You can’t directly return a built-in C-style array from a function, but you can do:
Return a pointer (heap-allocated), with careful ownership contract:The caller must
delete[]it.Return
std::vector<T>:The standard library handles memory safely and efficiently.Return
std::array<T, N>if size is compile-time known.
int* createArray(int n) {int* arr = new int[n];// fill arrreturn arr;}
std::vector<int> makeVec(int n) {std::vector<int> v(n);// fill vreturn v;}
Returning container types is usually safer and easier to maintain than raw arrays. When teaching pass array to function in C++, including return strategies rounds out the concept.
Wrapping up and next steps#
You now know the basics of using arrays in C++. Arrays are data types that we can use to store a collection of data under a single name. We’ve covered why and how we work with one-dimensional and two-dimensional arrays. We also discussed the role of pointers when passing arrays to functions.
To continue learning, check out Educative’s interactive learning path: C++ for Programmers. This program covers topics such as arrays, loops, and templates.
Happy learning!