Array in C/C++ Language, Brief Introduction

array in c

In this blog post, you will learn the arrays and their working. You will learn how to declare, initialize and access elements of an array with the help of some programming examples. Also some important points related to the array that should you know.

I will start from the beginner and explain each topic very clearly besides that I have already written many articles on array I will include their links at their appropriate location if you want you can check them. So let’s first understand that what is an Array?

 

What is an Array in C/C++?

An array is essentially a collection of elements. The data types for all elements must be the same and store at the contiguous memory location. You must remember that the element type shall be complete whenever the array type is specified. For example, if you want to store 5 integers, you can create an array for it.

//array of 5 integers/

int arr[5];

 

Each element of the array is individually referenced by using an index. We can easily access the elements using an index in square brackets. The index of the array always starts with 0. It means if you want to get the first element of the array then the index must be 0.

 

Array Syntax (Declaration of Array in C/C++):

The declaration of a pointer is very important because Array types are characterized by their element type and by the number of elements in the array. So at the time of the array declaration, you need to specify the number and type of the elements with the array name.

Array Syntax:

Data_Type  Array_Name [Array_Size];

For example, if you want to create an array of 10 integers, you have to declare an array as below expression. You can take an array name as your choice (but must follow the naming rule).

//Syntax of array of 10 integers.

int arr[10];

//Let's decode it.

Data_types ==>> int

Array_Size ==> 10

Array_Name ==> arr

 

Let’s see some below-mentioned examples to understand the declaration of an array.

int arr[5]; //Array of 5 integer


char arr[5]; //Array of 5 character


float arr[5]; //Array of 5 float


double arr[5]; //Array of 5 double

 

You should remember that that the size and type of an array cannot be changed once it is declared. Also, generally, the first element is at the lowest address and the last element is at the highest address in an array.

 

Why do we need arrays?

To understand why do we need arrays to let’s consider the situation, suppose you need to get 10 student’s age information and store it for some calculation. Also, we need to send the calculation result and age information to the server.

Since age (in the year) is an integer type, we can store it something like below,

//integer variables to store student age information

int ag1, age2, age3, age4, age5, age6, age7, age8, age9, age10;

 

If we use the integer variable like the above declaration, it will be very difficult to manipulate the data and send it to the server. The situation becomes more worst and difficult when the number of students goes beyond 100.

We can resolve this issue easily with the help of an array where we just need to create an array of size n, n is the number of students. For example, if you want to store and manipulate the age of 100 students you need to create an array of size 100. Here the idea of an array is to represent many instances by one variable (One derived type).

//Integer array of size 100

int arr[100];

 

How to Access Array Elements?

At the beginning of this blog post, I have already said each element of the array is individually referenced by using an index and we can easily access the elements using their index. Let’s consider an example for better understanding.

Suppose you declared an array of 5 integers. The index of the array always starts with 0, so you can see below the image aiData[0] is the first element of the array, the second element is aiData[1], and so on.

array in c

Note: If the size of an array is n, to access the last element, the (n-1) index is used.

 

If the array index is “i“, the “i” must follow this range 0<= i < n and must be an integral number, where n is the size of the array. Now let’s see how we access the aiData elements.

aiData[0]         ===>> First Element

aiData[1]         ===>> Second Element

aiData[2]         ===>> Third Element

aiData[3]         ===>> Fourth Element

aiData[4]         ===>> Fifth Element (Last element)

aiData[5]         ===>> Undefined behaviour (Going beyond the boundary of the array)

 

Note: Invalid index number returns undefined.

 

How to initialize an array?

We can initialize an array while declaring it. Like below example,

//Declaring and initializing an array

int aiData[10] = {0,1,2,3,55,6,7,8,8,9};

You can also initialize an array like this.

//Declaring and initializing an array 

int aiData[] = {0,1,2,3,55,6,7,8,8,9};

If you will not give the array size at the time of initialization, array size will be determined by the compiler. However, the compiler knows its size is 10 as we are initializing it with 10 elements.

Note: If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. The array type is completed at the end of its initializer list.

 

When initializing an array type, the initializer must be either a string literal (optionally enclosed in braces) or be a brace-enclosed list of initialized array members.

 

Let’s understand the array initialization, I have already written an article on it but because here we are discussing the array in detail. So I think array initialization is an important topic to discuss.

Initialization from strings:

String literal (optionally enclosed in braces) may be used as the initializer for an array of matching types. Let’s see few examples.

/*Defines ‘‘plain’’ char array objects
  str1 and str2 whose elements are initialized 
  with character string literals. */
char str1[] = "abc";
char str2[3] = "abc";


/* This declaration is identical to */
char str1[] = { 'a', 'b', 'c', '\0' };
char str2[] = { 'a', 'b', 'c' };


/*Initialized with wide characters of the wide string literal*/
wchar_t wstr[4] = L"猫"; 

// wstr has type wchar_t[4] and holds L'猫', '\0', '\0', '\0'

 

Initialization from brace-enclosed lists:

When an array is initialized with a brace-enclosed list of initializers, the first initializer in the list initializes the array element at index zero , and each subsequent initializer initializes the array element at index one greater than the one initialized by the previous initializer (except the designated Initializers- Since C99). Let’s see some examples.

// arr1 has type int[3] and holds 10,20,30
int arr1[] = {10,20,30}; 


// arr2 has type int[5] and holds 10,20,30,0,0
int arr2[5] = {10,20,30}; 

// arr3 has type int[3] and holds all zeroes
int arr3[3] = {0};

 

Designated Initializers -Since C99:

The C99 introduces a new mechanism to initialize the elements of the array. It allows you to initialize specific elements of the array in any sequence, you don’t need to initialize the array from the beginning.

In this method, if the size of the array is not given, then the largest initialized position becomes the size of the array (length of the array is the highest value specified plus one), and all uninitialized positions are initialized with 0.

To specify an array index, write ‘[index] =’ before the element value. For example

int a[6] = {[4] = 29, [2] = 15 }; 
              or
int a[6] = {[4]29 , [2]15 };

The above statement is equivalent to,

//array of 6 integers

int a[6] = { 0, 0, 15, 0, 29, 0 };

 

Let’s consider an example, where I create an integer array aiData, whose size is 20, and initialize it with the designated Initializers.

//integer array of size 20

int aiData[20] = { 1, 2, 3, [15] = 40, 5, [13] = 80, [18] = 89 };

 

In this example, the first three elements are initialized to 1, 2, and 3 respectively. Then index 15 (16th position of the array) is initialized with 40. The next element ( 17th ) is initialized to 5 and the indexes 13, 18 ( 14th, 19th position of the array ) is initialized with 80 and 89 respectively.

#include <stdio.h>
#include <string.h>

//Size of the static array
#define ARRAY_SIZE sizeof(aiData)/sizeof(aiData[0])

int main()
{
    int aiData[20] = { 1, 2, 3, [15] = 40, 5, [13] = 80, [18] = 89 };
    int iLoop = 0;
    printf("Stored elements of the array\n");
    for(iLoop=0; iLoop < ARRAY_SIZE ; iLoop++)
    {
        printf("     aiData[%d] =  %d\n",iLoop, aiData[iLoop]);
    }
    return 0;
}

Output:

c99 designated initializer

 

You can check the article to know more about the Designated Initializers, Read more.

 

Change Value of Array elements:

We can also assign a single value to the array using the subscript and index. Let’s consider the below example.

//Array of 5 integers

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

array in c

If I write the below expression,

//Assign 7 to third position

aiData[ 2 ] = 7;

 

The above statement assigns 7 to the 3rd element in the array. Now update list will look like the below image.

array in c pdf

Getting input from the user:

Here we learn how to take input from the user and store it in an array element. Let’s consider an example where we get the integer value from the user and store it in the array using the loop. In the case of an array, we know the exact size of the array, so we should use the “for loop“. It will get 5 elements from the user and print them.

#include<stdio.h>

int main()
{
    int arr[5];
    int i;

    //for getting 5 elements from user
    for(i = 0; i < 5; i++)
    {
        scanf("%d",&arr[i]);
    }

    printf("Print array elements\n");
    //printing all 5 elements
    for(i = 0; i < 5; i++)
    {
        printf("%d\n",arr[i]);
    }

    return 0;
}

 

 

Different types of Array in C:

There are several variations of array types: arrays of known constant size, variable-length arrays, and arrays of unknown size. Let’s see each type step by step.

Arrays of constant known size:

If the expression which decides the size of the array is an integer constant expression “N” with a value greater than zero, then it declares an array of size N (constant known size). For example,

//Array with constant expression

int arr1[10]; // integer constants are constant expressions

char arr2[sizeof(int)]; // sizeof is a constant expression

enum { ARRAY_SIZE = 10 };
int arr3[ARRAY_SIZE]; // enum constants are constant expressions

 

Arrays of constant known size can use array initializers to provide their initial values, let’s see some examples.

//declares int[3] initalized to 1,2,3
int arr[] = {1,2,3};


//declares char[4] initialized to 'a','b','c','\0'
char str[] = "abc";

 

Variable-length arrays:

C supports variable-length array (VLA) from the C99 standard. If the expression is not an integer constant expression, the declarator is for an array of variable size. The length of VLA is determined at run time instead of at compile time. The size of each instance of a variable-length array type does not change during its lifetime. Let’s see an example,

#include<stdio.h>

//VLA Supported since C99
void display(int n)
{
    int arr[n]; //VLA of size n
    int i =0;

    for (i = 0; i < n; ++i)
    {
        arr[i] = i;
    }

    //print array value
    for (i = 0; i < n; ++i)
    {
        printf("%d",arr[i]);
    }
}


int main()
{
    //calling function
    display(4);

    return 0;
}

Output: 0123

 

All variably modified (VM) declarations have to be at either block scope or function prototype scope. Array objects declared with the _Thread_local, static, or extern storage-class specifier cannot have a variable-length array (VLA) type. However, an object declared with the static storage class specifier can have a VM type (that is, a pointer to a VLA type).

Finally, all identifiers declared with a VM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions. Let’s see some examples for a better understanding.

extern int n;
int A[n]; // invalid: file scope VLA

extern int (*p2)[n]; // invalid: file scope VM

int B[100]; // valid: file scope but not VM

void funVla(int m, int C[m][m]); // valid: VLA with prototype scope

void funVla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA
{
    typedef int VLA[m][m]; // valid: block scope typedef VLA
    
    struct tag
    {
        int (*y)[n]; // invalid: y not ordinary identifier
        int z[n]; // invalid: z not ordinary identifier
    };
    
    int D[m]; // valid: auto VLA
    
    static int E[m]; // invalid: static block scope VLA
    
    extern int F[m]; // invalid: F has linkage and is VLA
    
    int (*s)[m]; // valid: auto pointer to VLA
    
    extern int (*r)[m]; // invalid: r has linkage and points to VLA
    
    static int (*q)[m] = &B; // valid: q is a static block pointer to VLA
}

 

 

Arrays of unknown size:

If the expression in an array declarator is omitted, it declares an array of unknown size. Except in function parameter lists and when an initializer is available, such type is an incomplete type.

If the array is an incomplete type, then it is completed, for an identifier of that type, by specifying the size in a later declaration (with internal or external linkage). For example,

#include<stdio.h>


int main()
{
     // the type of x is "array of unknown bound of int"
    extern int x[];

    printf("%d",x[1]);

    return 0;
}


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

Output: 20

 

Array with Qualifiers:

We can use the qualifiers ( const, volatile, restrict) with an array. Also, an array type and its element type are always considered to be identically qualified, except that an array type is never considered to be _Atomic-qualified (Since-C23).

typedef int A[2][3];

// array of array of const int
const A a = {{4, 5, 6}, {7, 8, 9}};

int* pi = a[0]; // Error: a[0] has type const int*

void *ptr = a; // OK until C23; error since C23

 

_Atomic is not allowed to be applied to an array type, although an array of atomic type is allowed.

typedef int A[2];
// _Atomic A arr0 = {0};    // Error
// _Atomic(A) arr1 = {0};   // Error

_Atomic int arr3[2] = {0};  // OK
_Atomic(int) arr4[2] = {0}; // OK

 

If you love online courses and want to learn C programming, you can check the below courses it will help.

 

 

Pointer and Array in C:

First, you need to understand that “pointers and arrays are not the same”. An array is essentially a collection of elements. The data type of all elements must be the same and store at the contiguous memory location.

In C-language pointer and array are very close to each other. Actually, In most contexts, array names decay to the pointers. So if aiData is an array of integers then “aiData” will be the address of its first element. You can also say that “aiData” is similar to &aiData [0].

Let’s see a program example,

#include <stdio.h>

int main()
{
    int aiData[5] = {10,5,6,7,8}; //integer array

    printf("Address of first element %p\n\n",&aiData[0]);

    printf("Address of first element %p\n\n",aiData);

    return 0;
}

Output:

 

Relationship between array and pointer in C:

Already I have explained that pointer and array are not the same. In most contexts, array names decay to pointers except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literals used to initialize an array.

Array elements stores in a consecutive memory block. We access the array elements using the index. But we can also access the array elements with the help of a pointer. Let’s see an example.

Consider the following example. Let suppose acBuffer is an array of characters.

#include <stdio.h>

int main()
{
    int i = 0;
    char acBuffer [ ] = {'a','t','i','c','l','e'};
    for(i = 0; i < sizeof(acBuffer); ++i)
    {
        printf("&acBuffer[%d] = %p\n", i, &acBuffer[i]);
    }
    printf("\nAddress of array acBuffer: %p\n\n", acBuffer);
    return 0;
}

Output:

relationship array and pointers in C-min

So acBuffer[0] is the 0th element of the array like that acBuffer[i] is the ith element of the array.

Notice that the address of &acBuffer[0] and acBuffer is the same. So from the above example, it is clear that &acBuffer[0] is equivalent to acBuffer . And, acBuffer[0] is equivalent to *acBuffer .

Similarly &acBuffer[1] is equivalent to acBuffer+1 and acBuffer[1] is equivalent to *(acBuffer+1).

So for ith elements, it would be.

*(acBuffer+ i) = acBuffer[i];
(acBuffer+ i) = &acBuffer[i];

Let’s see an image for a better understanding,

Note: Because acBuffer is an array of characters then &acBuffer[i] type is the pointer to the character and its value is the address of the ith element of the acBuffer.

 

Simple expression to decay an array into a pointer:

arr[i] = *(arr+i) ————————->1D array decay in form of pointer


arr[i][j] = *(arr[i]+j); ————————–> 2D array decay in form of 1D array and pointer.

Using the first expression we can also write
arr [i][j] = *(*(arr+ i) + j) ———————->2D array decay in form of pointer

 

I believe now you are able to understand the relationship between an array and pointer. Now it’s time to understand that how we can access the array elements using the pointer.

To access the element of the array through the pointer we need to create a pointer type the same as the array first element (here, a pointer to char)

char * pcBuffer = NULL;
pcBuffer = acBuffer; // character pointer point the address of first element

 

Now using the pointer you can access all elements of the array.

#include <stdio.h>

int main()
{
    char acBuffer [] = {'a','t','i','c','l','e'};   // array of character
    int i = 0;
    char *pcBuffer = NULL; // character pointer
    pcBuffer = acBuffer;
    for(i =0; i <6; i++)  // access the array element using the pointer
    {
        printf("pcBuffer[%d] = %c  or  *(pcBuffer+%d) = %c \n\n",i,pcBuffer[i],i, *(pcBuffer+i));
    }
    return 0;
}

Output:

 

Difference between pointer and array:

From the beginning, I am saying that the pointer and array are not the same. Here we will see the difference between the array and pointers. I have already written a blog post on it if you want you can check it, “Difference between the array and pointers“.

The basic difference between array and pointers is that the array is a sequence of elements of the same type that occupy a contiguous area of memory while the pointer is a special variable that stores a memory address.

The array is a non-modifiable type while we can change the address pointed by pointers if the pointer is not a constant type. Let’s see an example code where I am trying to modify the array.

Consider the below example,

In the below example when trying to modify the array then we will get the compiler error.

array using pointer

 

 

Access Array elements out of their bound:

If you will try to access the array beyond its boundary the behavior would be Undefined (UB). The C language explains only what should happen if you access the elements within the bounds of an array. It is left undefined what happens if you go out of bounds.

C arrays are contiguously allocated nonempty sets of objects, it is the reason there are no bounds checking. But you can handle it in a clever way by putting some conditions. Let’s understand it with an example.

Suppose you declared an array of 5 elements. Let’s say,

int aiData[5];

There will be no issues if you will access the array elements from aiData[0] to aiData[4].  But issues arrive when you will try to access aiData[8]. The element is not available. This may cause undefined behavior(UB).

#include <stdio.h>

int main()
{
    int aiData[5];
    
    aiData[3]=4; // Ok
    aiData[4]=4; // Ok
    
    aiData[8]=3;//Undefined Behaviour
    aiData[6]=4;//Undefined Behaviour
    aiData[5]=3; //Undefined Behaviour
    
    return 0;
}

 

Multidimensional arrays:

We have already discussed the array and the arrays which I have taken in example code was one-dimensional arrays. I have already discussed the multidimensional array in the separates blog posts. But let’s see some short notes on the multidimensional array.

In C programming, you can create an array of arrays. These arrays are known as multidimensional arrays and the syntax of creating the multidimensional array is simple like a 1D array.

Syntax of N-Dimensional array in C:

Data_Type  Array_Name  [size1] [size2] [size3]…. [sizeN];

For example,

int aiData [3][3] = { { 9, 6, 1 }, { 144, 70, 50 }, {10, 12, 78} };

Here, aiDatais a 2-D (two-dimensional) array. The array can hold 9 elements. You can think of that array as a table with 3 rows and each row has 3 columns.

 

Note: If Arr is an n-dimensional array (n ≥ 2) with dimensions i × j × · · · × k, then Arr is converted to a pointer to an (n − 1)-dimensional array with dimensions j × · · · × k.

 

Let’s see an example code of a two-dimensional array to store and print values. It will help you to understand that how you can store and access the value of the 2-D array in C.

#include <stdio.h>

int main()
{
    //Declare 2D array
    int aiData [3][3];
    int iRow =0, iCol =0;

    // Store value in 2D array
    for( iRow = 0; iRow < 3; iRow++ )
    {
        for( iCol = 0; iCol < 3; iCol++ )
        {
            aiData[iRow][iCol] = 13;
        }
    }

    printf("Stored value of 2D array is \n\n");

    //Access the stored value from the 2D array
    for( iRow = 0; iRow < 3; iRow++ )
    {
        for( iCol = 0; iCol < 3; iCol++ )
        {
            printf("\n aiData[%d][%d] = %d",iRow,iCol,aiData[iRow][iCol]);
        }
    }

    return 0;
}

Output:

accessing 2d array in c

 

 

Few keynotes related to the C Arrays:

  • 0th is the first index of the array. If the size of an array is n, to access the last element, the (n-1) index is used.
  • Invalid index number returns undefined.
  • There are no bounds checking in C Arrays.
  • You can use qualifiers with the array.
  • We can pass array within the function and if except some context arrays decay in pointers.
  • We can not create an array of void but can create an array of void *.

 

Recommended Articles for you: