All about Arrays in C/C++ - Part I

Introduction

This article tries to cover all about Arrays like from it's definition till it's usage using a single dimension.

Background

Definition

An array is a built-in Data Structure that holds a sequence of variables of same data type, that are stored in a contiguous memory locations.

Some characteristics about Arrays

The elements of an array are indiced and accessed by their index, where as first position/index of an array starts from "0" and last position is sizeOfArray-1 !!

By default, Arrays are not initialised.

Like any other variable, an array must be declared before it is used.

Each element in an Array must be printed individually.

An Array cannot be copied/assigned/compared from another Array directly, these operations have to be done element by element basis.

Name of the Array is nothing but address of/pointer to the first element of the Array

There is no Array bound checking done in C. Trying to access the position at sizeofArray or beyond that is an Error and results in an undefined behaviour.

ArrayName indicates the base address or address of the first element in the Array.

Address of any element in a Single Dimensional Array can be caclulated as
ElementAddress = BaseAddress+ indexOfTheElement * SizeOfTheElement

Declaration of an Array

Declaration of an array takes data_type of the elements to be stored, variable name followed by the size of the array wrapped within square brackets as below:

data_type variableNameOfArray[no_elements]

For Example:

int employee[5] = {10,20,30,40,50};

where employee is the name of a single dimensional array variable, that can hold 5 variables of integer type. So, the number 5 indicates the size of the array employee.
Where "0", "1", "2", "3", "4" shows the indices of the array employee. Any element of an Array, can be accessed by using it's respective index inside [] as below:

printf("%d", employee[2]);

This will access and print the 3rd element i.e. 30 of the Array employee.

Array Initialization

We can Initilize an Array when it is declared. Initializers are constant values/expressions seperated by a comma and enclosed within flower braces {} as below:

dataType variableNameOfArray[no_elements] = {values}

int employee[5] = {120, 121, 122, 123, 124};

As a convinience, if you leave out the size of the array, it creates it with the exact size to hold that number of initial values.

int employee[] = {120, 121, 122, 123, 124};

The elements in the aggregate that are not given initilizers are default initialized according to their data type.

Address to a first element of an Array is nothing but Array name itself and it is a pointer of it's element type or Array type. Adding 1 to this pointer, gives the address of the next element in the Array. It means, it adds with 1*sizeOf(elementDataType) to the base address of the array.

For Example:

Code:

int array[3] = {10,20,30};
cout<<"*(array+1)"<<*(array+1)<<endl;

Results the content of second element i.e. "20". array+1 adds (1*4) to the base address i.e. array and gives the content of that address. Where 4 is size of an int nothing but size of an element of array here!!

In other way we can say

array or array+0 ----> &array[0]

*array -----> array[0]

And

array+1 ------> &array[1]
*(array+1) -----> array[1]

.
.
.

array+i --------> & array
*(array+i) ------> array

Same way, we can as well do subtraction here.

By seeing these examples, we can say that array behaves like a pointer, but really it is not. As we cannot assign values to it as below:

Code:

int arr[5];
int j;
arr = &j // gives complation error!!

But however we can assign an array name to a pointer as below:

Code:

int arr[5];
int *p = arr; or
p = &arr[0]

Static and Dynamic Array allocation

int employee[5];

When an Array is declared like above, the memory is allocated for all the elements of it and it will be there till the life time of the program. This is called as Static Array allocation. So, here the developer knows in advance the size of the Array at compile time itself.

In case, if the developer does not know the Array size at compile time, then Array can be alllocaed at run time as well. This is called as Dynamic Allocation of an Array.

Also, if some of the elements in character Arrays are not given initizers, then they will be initilized with NULL or '\0' character.As like initeger Arrays, character arrays are also can be initilized with NULL character just by assigning them with {} as below.

char array[8] = {};

Otherwise, by Default, it will be initilized with some junk characters.

Array as an Argument to a function

A function can receive Array as an argument with any of the below forms:

As a pointer to an Array like int func(int *array);

As a sized Array like int func(int array[3]);

As an unsized Array like int func( int array[]);

As a reference to an Array like void func(int (&arr)[3]);

But always an array name that as a function argument is converted to a pointer to the start of array, at compile time itself, by the compiler. So any reference to that array inside the function is treated as a pointer reference.

If we see the above code snippets, array when it is passed as an argument to a function, can be assigned to another array as it is treated always as a pointer. Whereas we cannot do the same in main function, it would give compilation error, as we are trying to change the array name itself, which cannot be done.

The above code snippet confirms that array which is passed to as an argument to function, is treated as a pointer inside the function as the sizeof that argument results with sizeof a pointer and not sizeof the Array.

Also, by giving/sending a pointer to any intermediate element of an Array to a function, we can just pass the slice/last part of the array from that intermediate point.