C++ 1D Arrays

Sun Oct 12 2025
Updated: Tue Oct 14 2025
Facebook share linkTwitter/X share linkLinkedIn share linkReddit share linkReddit share link

Introduction


Declaring

Recall declaring a variable:

int i;

Which creates a single space in memory able to hold a 32-bit whole number:

Variable allocated in main memory.

This can be expanded to be an array of any size (limited only by the amount of memory in the computer) by adding [SIZE] after the identifier:

dataType identifier[SIZE];

Where dataType is any data type to make an array of, identifier is any valid identifier to call the array, and [SIZE] is an integer that represents how many items are needed in the array. For example the following:

int a[3];

Will create an array with 3 elements:

Array with 3 elements allocated in main memory.

The SIZE can be any integer value but this value must be a literal or constant, not a variable. In C++ all arrays are contiguous, one item after another, in main memory. In the image above the addresses 0x6dfed4 0x6dfed8 0x6dfedc each increase by 4 as the array is holding integers which take up 4 bytes. In order to guarantee that there is enough memory for the array to be contiguous in memory the compiler must allocate space for the array, which happens as the compiler makes the a.out file that will eventually be executed. So the compiler must know prior to execution what size the array must be. So take the following into consideration:

int size = 0; cout << “Size:; cin >> size; int a[size];

At this point the user is entering a size when the program is executing, after the program has compiled. So now it is impossible for the compiler to be able to know how many items there are in the array. Thus the compiler can not allocate contiguous memory for the array. Therefore, creating arrays with variable sizes is not allowed in C++ or the following warning will occur at compile time:

test.cpp:11:9: warning: variable length arrays in C++ are a Clang extension [-Wvla-cxx-extension] 11 | int a[size]; | ^~~~ test.cpp:11:9: note: read of non-const variable 'size' is not allowed in a constant expression test.cpp:7:7: note: declared here 7 | int size = 0; | ^

This warning is suppressed in some versions of C++ as it is fixed, but in many versions it is not (the version can be changed when compiling using the flag -std=VERSION when compiling such as g++ main.cpp -std=c++11 which will cause C++ 11 to be used for this compilation) so it is generally discouraged to do make variable lengthed arrays.

The size of arrays are generally held in constants as constants can not be changed after being defined, thus the compiler will be able to know what size the array is. For example, the following SIZE can not be changed after declaration thus it can be used as an array size without problems:

const int SIZE = 4; int a[SIZE];

The only time constants can not be the size of an array is if they are made with a variable, otherwise the same problem and warning persists. For example the following will produce the same error above:

int size = 4; const int SIZE = size; int a[SIZE];

Accessing Information

To access information within a declared array it must be accessed by the values index, or an item's position within an array. Consider the following:

int a[3]; cout << a << endl;

Only an address will be output:

0x16f8aee5c

This is because since the array is contiguous in memory only the first item’s address needs to be memorized. Then the size of the data type the array holds can be added to the address to get to the next item, or 2 times to get the item after that and so on. For example in the array:

Array with 3 elements with indices 0 through 2 allocated in main memory.

Each element has an index 0 through 2 which can have its address calculated using:

address=baseAddresss+indexdataTypeSizeaddress = baseAddresss + index * dataTypeSize

Such as 0x6dfed4 = 0x6dfed4 + 0 * 4, 0x6dfed8 = 0x6dfed4 + 1 * 4 and 0x6dfedc = 0x6dfed4 + 2 * 4 (since addresses are in hexadecimal the final address goes to c because c - 4 + 8 in hexadecimal). In C++ this math luckily does not need to be performed, rather array elements can be accessed via their indices using [index] after a declared array’s identifier which will cause this math to be performed under the hood to access the selected element:

arrayIdentifier[index];

Where index is a whole number value in the range:

0indexsize10 \le index \le size - 1

The indices of arrays always start at 0 and since they include zero they go up to the arraySize - 1.

So for an array int arr[3] each of its elements can be accessed and values placed into them using the assignment operator:

int arr[3]; arr[0] = 5; // 0th item in the array arr[1] = 6; // 1st item in the array arr[2] = 7; // 2nd item in the array

Which places the values into the respective indices of the array:

Array with 3 elements with indices 0 through 2 allocated in main memory with values 5, 6, and 7 in their respective indices.


Printing

To print arrays they must be linearly worked through, outputting each element individually. To do this a loop can be used to work through the valid indices of the array, outputting each element as it iterates:

const int size = 5; int arr[size]; for (int i = 0; i < size; i++) { cout << arr[i] << endl; }

The loop control variable i is initialized to 0 and iterates through the size - 1 iteration until stopping, outputting a new element (the next element) from the array each time the loop body is executed. But this loop will not produce any predictable output, rather it will produce output such as:

268435455 1840393992 1 250773528 2

Or:

268435455 1866870536 1 126572846 2

Which are just random values from main memory that were set by programs that had the same memory previously. These values must be cleared by initializing the array.


Initialization

Since arrays have garbage values inside of them they need to be initialized to avoid many invalid values being introduced to the program. There are 3 ways to initialize arrays

  1. At declaration.

  2. In a loop using assignment or input.

  3. From a file (discussed later).

At Declaration

To initialize an array at declaration assign the array an array literal at declaration. Array literals can be declared by enclosing a comma separated list of literal data of the same type in curly braces {}. For example the list 1 2 3 4 can be stored into a literal array in C++:

{1, 2, 3, 4}

This literal array can be assigned to a variable using the assignment operator:

int arr[] = {1, 2, 3, 4};

And when there is no size placed in the [] then the array will assume the size of the literal array (which in this case is 4). A value can also be placed in the square brakes to explicitly give a size to the array:

int arr[4] = {1, 2, 3, 4};

If the size of the variable array is the exact same as the literal array, each literal array element will be placed in its respective spot in the array. If the size in the square brackets is too small:

int arr[3] = {1, 2, 3, 4};

Then the following compiler error will occur:

error: excess elements in array initializer 7 | int arr[3] = {1, 2, 3, 4}; |

Lastly, if the value in the square brackets is larger than the size of the literal array:

int arr[4] = {1};

Then 1 0 0 0 will be placed in arr as the elements of the literal array will be placed into their respective elements in the variable array. Then the rest of the elements in the variable array that do not receive a value from the literal array will be set to 0 in the case of integral and floating point values, and the empty string for strings. So using:

int arr[4] = {};

Will initialize all 4 of the elements in arr to 0 (i.e. 0 0 0 0)

In a Loop

Arrays can also be initialized in a loop similar to printing the array, but rather than outputting each value, storing values with the assignment or stream extraction operators. To assign a value to each element in the array:

const int size = 3; int arr[size]; for (int i = 0; i < size; i++) { arr[i] = 0; }

The loop initializes arr to 0 0 0 by visiting each element iteratively and setting each element individually to 0 using the assignment operator.

To do similar with user input a user would need to be prompted and a value read in and stored each iteration of the loop:

const int size = 3; int arr[size], input = 0; for (int i = 0; i < size; i++) { cout << “Whole number:; cin >> input; arr[i] = input; }

Now the 3 elements of arr will be whatever the user enters. Although the user could enter invalid numbers which could be checked with selection and recovered from using more repetition.


Copying

Using the assignment operator a literal array may only be copied to a variable array. If a variable array is assigned to another variable array:

int a[3] = {}; int b[3] = a;

The following compiler error will occur:

error: array initializer must be an initializer list 8 | int b[3] = a; | ^ 1 error generated.

As only a literal array may be assigned to a variable array. Therefore to copy the values of one literal array to another first 2 arrays must be created of equal size:

int size = 3; int a[size] = {1, 2, 3}; int b[size] = {};

Then the array to be overwritten can be overwritten element by element from the second array in a loop:

int size = 3; int a[size] = {1, 2, 3}; int b[size] = {}; for (int i = 0; i < size; i++) { b[i] = a[i]; }

Now if an element is changed in a then b will be unaffected since it is a separate array that has copies of all the original values a had:

a[0] = 4; // b[0] is still 0 as it was not changed

In order to change elements in b then b would have to be directly accessed and its elements changed:

b[0] = 10; // a[0] is still 4 as it was not changed

Out of Bounds Segmentation Fault 11

When working with arrays invalid indices can be accessed without error, for example:

int a[3] = {}; cout << a[3] << endl;

Goes out of bounds as the index 3 is one larger than the last index of size - 1 which the size of the array is 3 making the last index 2. But no error is output, just whatever random value gets made up from the bits that are at that memory location which make up some other component of the program:

2

This value is unpredictable as it can be any value since the program may arrange memory slightly differently on any given run of the program.

Now consider the following:

int arr[1]; for (int i = 0; i < 5; i++) { arr[i] = i; cout << arr[i] << endl; }

Where the program accesses items in indices 1 2 3 4 which are not valid indices of the array. When the array accesses and edits an element much past the end of the array an error similar to the following occurs:

zsh: segmentation fault ./a.out

Which can appear differently depending on the compiler (i.e. seg fault, seg fault 11, segmentation fault 11, etc.). A segmentation fault is an error which occurs when an invalid location in memory has been accessed or edited. It is important to note that here it worked only 4 indices past the end of the array but sometimes it takes longer for an error to occur when iterating past the end of an array. It just takes accessing a true invalid location in memory.

The easiest way to find seg faults is to build code in small chunks compiling after every few lines of code written. This way when a seg fault occurs it must have been within the past few lines so it can easily be found. If a large portion of code is written without compiling then each loop where arrays are accessed iteratively needs to be analyzed. The code for each loop can be isolated and array access indices output until the invalid indices are found, then the code can be further analyzed as to why it is going out of bounds from there.


Example: Simple Game Inventory

Write a program that holds an inventory of item names in an array of 10 strings. The inventory should initially hold “boots”, “gloves” and a “sword”. The user should then be able to add an item to the inventory in any position.

An array first needs to be created to represent the inventory, then it must be initialized with the “boots”, “gloves”, and “sword”. The initial inventory can then be displayed:

#include <iostream> using namespace std; int main() { const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } return 0; }

The inventory array holds the initial values from the literal array {"boots", "gloves", "sword"} with the values in the same respective indices of the variable array as the literal array. The inventory is then looped through and each item either output if there is an item (no item is the empty string so if inventory[i] != "" is true then there is an item at that index). Otherwise there is no item at the index and ”_” is output to show something can be added to the inventory later in the program.

Then after each item that is not the last item a comma is output. The last item is at index inventorySize - 1. So when i != inventorySize - 1 is true then the program is not at the last item so a comma is output.

A new item can then be read into the inventory by getting the slot the item should go into, followed by the item to inserted into the inventory:

#include <iostream> using namespace std; int main() { int slot = 0; string item = ""; const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } // get slot to add item to cout << "What index (0-" << inventorySize - 1 << ") to add to? "; cin >> slot; // get item to add cout << "What item to add? "; cin.ignore(256, '\n'); getline(cin, item); // add item to inventory inventory[slot] = item; return 0; }

The index in the inventory to save an item into is read into slot and the name of the item to item. The slot is then used as an index into inventory to save item to. But there is an issue with this if the user enters a negative or excessive index such as -1 or 10000 a segmentation fault will occur as these are invalid memory locations. To fix this a selection statement must be used to stop the program from trying to insert a value into the inventory when an invalid index is entered:

#include <iostream> using namespace std; int main() { int slot = 0; string item = ""; const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } // get slot to add item to cout << "What index (0-" << inventorySize - 1 << ") to add to? "; cin >> slot; // invalid index selected if (cin.fail() || slot < 0 || slot >= inventorySize) { cout << "invalid slot selected\n"; return 0; } // get item to add cout << "What item to add? "; cin.ignore(256, '\n'); getline(cin, item); // add item to inventory inventory[slot] = item; return 0; }

If there is input failure, the index is too small slot < 0, or the index is too large slot >= inventorySize then the program outputs an error and quits. Otherwise the program continues to get the name of the item to add and then stores the item at the appropriate index. The new updated inventory can then be displayed similar to how the initial inventory was displayed:

#include <iostream> using namespace std; int main() { int slot = 0; string item = ""; const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } // get slot to add item to cout << "What index (0-" << inventorySize - 1 << ") to add to? "; cin >> slot; // invalid index selected if (cin.fail() || slot < 0 || slot >= inventorySize) { cout << "invalid slot selected\n"; return 0; } // get item to add cout << "What item to add? "; cin.ignore(256, '\n'); getline(cin, item); // add item to inventory inventory[slot] = item; // show updated inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } return 0; }

So if the user wants to add a “dagger” at index 5 then these values are input and the following interaction is produced:

Inventory: boots, gloves, sword, _, _, _, _, _, _, _ What index (0-9) to add to? 5 What item to add? dagger Inventory: boots, gloves, sword, _, _, dagger, _, _, _, _

Example: Adding Multiple Inventory Items

Add to the Simple Game Inventory Example the ability to add items to the inventory until the user has added as many items as they want to the inventory.

Once the user has added an item they can be prompted to add another item:

#include <iostream> using namespace std; int main() { int slot = 0; string item = ""; char selection = ‘a’; const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } // get slot to add item to cout << "What index (0-" << inventorySize - 1 << ") to add to? "; cin >> slot; // invalid index selected if (cin.fail() || slot < 0 || slot >= inventorySize) { cout << "invalid slot selected\n"; return 0; } // get item to add cout << "What item to add? "; cin.ignore(256, '\n'); getline(cin, item); // add item to inventory inventory[slot] = item; // show updated inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } cout <<(a)nother item (any other char to quit)?; cin >> selection; return 0; }

Whatever character the user enters will be placed into selection and if it is ’a’ then the program can loop back to asking the user for another item:

#include <iostream> using namespace std; int main() { int slot = 0; string item = ""; char selection = ‘a’; const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } do { // get slot to add item to cout << "What index (0-" << inventorySize - 1 << ") to add to? "; cin >> slot; // invalid index selected if (cin.fail() || slot < 0 || slot >= inventorySize) { cout << "invalid slot selected\n"; return 0; } // get item to add cout << "What item to add? "; cin.ignore(256, '\n'); getline(cin, item); // add item to inventory inventory[slot] = item; // show updated inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } cout <<(a)nother item (any other char to quit)?; cin >> selection; } while (selection == ‘a’); return 0; }

Now the program will loop storing items until they choose not to, unless input failure happens or an invalid index is entered. In these cases the program will terminate. To fix this the program can simply continue to the next iteration when error occurs:

#include <iostream> using namespace std; int main() { int slot = 0; string item = ""; char selection = ‘a’; const int inventorySize = 10; string inventory[inventorySize] = {"boots", "gloves", "sword"}; // show initial inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } do { // get slot to add item to cout << "What index (0-" << inventorySize - 1 << ") to add to? "; cin >> slot; // invalid index selected if (cin.fail() || slot < 0 || slot >= inventorySize) { cout << "invalid slot selected\n"; cin.clear(); cin.ignore(256, '\n'); continue; } // get item to add cout << "What item to add? "; cin.ignore(256, '\n'); getline(cin, item); // add item to inventory inventory[slot] = item; // show updated inventory cout << "Inventory: "; for (int i = 0; i < inventorySize; i++) { // display item if (inventory[i] != "") cout << inventory[i]; else cout << "_"; // display comma after each item except the last if (i != inventorySize - 1) cout << ", "; else cout << endl; } cout <<(a)nother item (any other char to quit)?; cin >> selection; } while (selection == ‘a’); return 0; }

The return 0 is changed to continue so if an error happens then the program will just stop executing the loop body and recheck the loop condition. But since input failure is being checked clear() and ignore() must be used to clear any input failure that occurs.

Now the user can add as many items as they want:

Inventory: boots, gloves, sword, _, _, _, _, _, _, _ What index (0-9) to add to? error invalid slot selected What index (0-9) to add to? -1 invalid slot selected What index (0-9) to add to? 10 invalid slot selected What index (0-9) to add to? 9 What item to add? platebody Inventory: boots, gloves, sword, _, _, _, _, _, _, platebody (a)nother item (any other char to quit) ? a What index (0-9) to add to? 5 What item to add? dagger Inventory: boots, gloves, sword, _, _, dagger, _, _, _, platebody (a)nother item (any other char to quit) ? q

Reading from a file

Manually inputting data into arrays gets tedious after it is done a few times. For this reason most data that is going to be placed into arrays comes from somewhere rather than user input. Many times data for arrays comes from files thus basic file i/o must be combined with 1D arrays to facilitate data being placed from files into 1D arrays.

Consider the file numbers1.txt which contains:

7 2 3

This file can be read into an array using the following program:

#include <fstream> using namespace std; int main() { // create array const int SIZE = 3; int nums[SIZE] = {}; // open numbers1.txt ifstream in; in.open(“numbers1.txt”); // get each number as separate reads in >> nums[0] >> nums[1] >> nums[2]; // close the input file in.close(); return 0; }

Which will only allow a file of size 3 to be handled. But what about when the same program needs to handle numbers2.txt which contains:

7 2 3 1

How can the program still handle this input while handling numbers1.txt? In C++ using simple arrays (non-dynamic arrays without pointers) the only way to handle this is to make an array large enough to handle the largest input, then read into the array up until the index needed, then only use the part of the array read into when the array is needed.

For example if files with up to 50 elements are needed but sometimes files have less elements, then an array of size 50 should be made and then only the indices starting from the beginning of the array used per input size from the file. Doing this creates 2 distinct parts of the array:

Array with 3 elements allocated in main memory.

The front used part of the array which is filled by values from the file, and the back unused part which is not being used by files with less inputs then the size of the array. This divide in the array can be kept track of with a count variable which is incremented once each time a new item is placed into the array. For example to handle files up to 5 inputs an array can be made and the file read from:

#include <fstream> using namespace std; int main() { // create array const int SIZE = 5; int count = 0, nums[SIZE] = {}; // open numbers1.txt ifstream in; in.open(“nums.txt”); // read from the file until empty while (!in.eof()) { // place a value from the file into the array in >> nums[count]; // count the amount of reads (where the divide is in the file) count++; } // close the input file in.close(); return 0; }

When a valid input is read the count is increased by 1 so if nums.txt only contains:

1

Then count will only be incremented once leaving it at 1 which is where the split is in the array for this file. On the other hand, if nums.txt contains:

1 2 3 4 5

Then count will be incremented 5 times leaving it at 5 which is where the split is in the array for this file. If however nums.txt contains too many values:

1 2 3 4 5 6

Then the program is at risk of a segmentation fault as the value 6 will be read in from the end of file controlled loop which will be placed in an invalid location of the array. To avoid this a simple test to see if the array is full after each read can be implemented:

#include <fstream> using namespace std; int main() { // create array const int SIZE = 5; int count = 0, nums[SIZE] = {}; // open numbers1.txt ifstream in; in.open(“nums.txt”); // read from the file until empty while (!in.eof()) { // place a value from the file into the array in >> nums[count]; // count the amount of reads (where the divide is in the file) count++; // see if array is full if (count == SIZE) { // stop reading if array is full cout << “Array full -- stopping reading file\n”; break; } } // close the input file in.close(); return 0; }

The array is full when count == SIZE, so when this check is true a message is output and the loop to read from the file until the end of the file is terminated early using break. This causes any segmentation faults to be avoided when reading from the file into the array.


Linear Search

An array linear search is when an array is searched from end-to-end to find an element of a specific value. When the desired value is found the index is memorized and the search concluded. The index of the found item can then be used to lookup the item as needed.

Take the array {2, 7, 1, 4, 3, 5, 9} which can be searched for a value the user enters. First the user must be prompted for a value to find:

#include <iostream> using namespace std; int main() { // get value to search for int searchingFor = 0; cout << “What value to find in the array:; cin >> searchingFor; return 0; }

Then the indices of the array can be iterated through checking if the current number the loop is at is the the number being looked for:

#include <iostream> using namespace std; int main() { // get value to search for int searchingFor = 0, i = 0; cout << “What value to find in the array:; cin >> searchingFor; // create array const int SIZE = 7; int nums[SIZE] = {2, 7, 1, 4, 3, 5, 9}; // read from the file until empty for (i = 0; i < SIZE; i++) { if (nums[i] == searchingFor) { break; } } return 0; }

When nums[i] == searchingFor this means the item that at index i is the value the user is searchingFor thus i is the index of the item being searched for so the loop can stop executing with break. Since i was declared prior to the for loop the value i was set to in the loop will persist after the loop, thus if the loop hits the break statement i will persist the value it contained when i was the used as the index where the number to search for was found. The index of the value in i can then be used as needed in the program:

#include <iostream> using namespace std; int main() { // get value to search for int searchingFor = 0, i = 0; cout << “What value to find in the array:; cin >> searchingFor; // create array const int SIZE = 7; int nums[SIZE] = {2, 7, 1, 4, 3, 5, 9}; // read from the file until empty for (i = 0; i < SIZE; i++) { if (nums[i] == searchingFor) { break; } } // output if the value was found cout << searchingFor; // value found if (i != SIZE) { cout << “ is at index “ << i << endl; } // value not found else { cout << “ is not in the array\n”; } return 0; }

Here the program just outputs the index if the found item if it is found, otherwise an error message is output. The check i != SIZE works here because if the value is not found then the for loop will terminate from i being incremented to the same value that SIZE is. Thus if i and SIZE have the same value it is because searchingFor was not found which can be used here to determine what message to output.



Terms

  1. Segmentation Fault - An error which occurs when an invalid location in memory has been accessed or edited.

  2. Array Linear Search - When an array is searched from end-to-end to find an element of a specific value


Questions

To Be Added Later