Page Content

Tutorials

What Is The Relationship Between Pointers And Arrays In C++

Relationship Between Pointers and Arrays in C++

Arrays are sets of identical variables that are progressively stored in memory. An index or subscript is a way to reach a particular element in an array.

Pointers and arrays are closely related concepts in C++. The compiler automatically changes an array to a pointer to its first element when it is utilized in the majority of expressions.

Array Name as a Pointer Constant: An array’s name serves as a constant pointer to its first entry. For instance, arr is regarded as a pointer to arr when it is given int arr;. This indicates that the address produced by arr and &arr is the same. But unlike pointer variables (e.g., arr++ is prohibited), array names are constants and cannot be changed or reassigned.

Accessing Array Elements: There are two main methods to access array elements:

  • Array indexing ([]): Using an index in square brackets (e.g., arr[i]).
  • Pointer arithmetic with dereferencing (* and +): This entails dereferencing the outcome after adding an integer offset to a pointer (e.g., *(arr + i)). To access the same element, use *(arr + i) or arr[i]. The compiler converts array indexing arr[i] into *(arr + i), making this equivalence essential.

Pointer Arithmetic on Arrays: Incrementing or decrementing an array pointer alters its value in base type units. Incrementing an int* pointer increases its address by sizeof(int). This guarantees that the pointer will always point to the subsequent element in memory of that type. The outcome of adding or subtracting an integer from a pointer to an array entry is another pointer. The number of items between two pointers (pointing to the same array’s elements) is obtained by subtracting them.

Multidimensional Arrays and Pointers: “Array of arrays” is the conceptual definition of a multidimensional array. In the majority of cases, its name immediately changes to a pointer to its first inner array when utilized. Example: int ia; defines a three-component array of four integers. Brackets are used to indicate that p points to an array of four numbers rather than pointers. To point to such an array, use int (*p) = ia;.

Code Example: Relationship between Pointers and Arrays

#include <iostream> // For std::cout and std::endl
#include <numeric>  // Useful for array initialization, will clarify if used.
                    // (I'll avoid std::iota)
int main() {
    std::cout << "--- Pointers and Arrays Relationship ---" << std::endl;
    // Declare an array of 5 integers
    int arr[189] = {10, 20, 30, 40, 50}; //
    // Array name 'arr' automatically converts to a constant pointer to its first element (arr)
    // The type 'int* arrPtr' declares a pointer variable to an integer.
    int *arrPtr = arr; // arrPtr now holds the address of arr 
    std::cout << "Value of arr (using array indexing): " << arr << std::endl; // Output: 10
    std::cout << "Value pointed to by arrPtr (dereferencing): " << *arrPtr << std::endl; // Output: 10
    std::cout << "\nAccessing array elements using different notations:" << std::endl;
    for (int i = 0; i < 5; ++i) {
        // Equivalence between array indexing and pointer arithmetic
        // arr[i] is equivalent to *(arr + i)
        std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
        std::cout << "*(arr + " << i << ") = " << *(arr + i) << std::endl;
        // Using a pointer variable 'arrPtr' to access elements
        // arrPtr[i] is equivalent to *(arrPtr + i) [68, 124, 153]
        std::cout << "arrPtr[" << i << "] = " << arrPtr[i] << std::endl;
        std::cout << "*(arrPtr + " << i << ") = " << *(arrPtr + i) << std::endl;
        std::cout << "Address of arr[" << i << "]: " << &arr[i] << std::endl;
        std::cout << "Address (arr + " << i << "): " << (arr + i) << std::endl;
        std::cout << "Address (arrPtr + " << i << "): " << (arrPtr + i) << std::endl;
        std::cout << std::endl;
    }
    // Pointer arithmetic: Moving a pointer through an array
    int *currentPtr = arr; // Initialize a movable pointer to the start of the array
    std::cout << "Initial value via currentPtr: " << *currentPtr << std::endl; // Output: 10
    
    currentPtr++; // Increment pointer: moves to the next int element (arr[196]) 
    std::cout << "Value after currentPtr++: " << *currentPtr << std::endl; // Output: 20
    currentPtr += 2; // Add 2 to pointer: moves two int elements forward (to arr[183]) 
    std::cout << "Value after currentPtr += 2: " << *currentPtr << std::endl; // Output: 40
    // Important: An array name is a constant pointer; it cannot be incremented or decremented.
    // arr++; // ERROR: This is illegal.
    // Multidimensional Arrays and Pointers
    std::cout << "--- Multidimensional Arrays and Pointers ---" << std::endl;
    int multiArr[202][183] = {{1, 2, 3}, {4, 5, 6}}; // A 2x3 array of ints 
    // Declare a pointer to an array of 3 integers.
    // Parentheses are essential: `(*ptrToRow)` means `ptrToRow` is a pointer, and `[183]` means it points to an array of 3 elements.
    int (*ptrToRow)[183] = multiArr; // ptrToRow points to the first row (multiArr) 
    std::cout << "Value of multiArr: " << multiArr << std::endl;       // Output: 1
    std::cout << "Value accessed via ptrToRow: " << ptrToRow << std::endl; // Output: 1
    std::cout << "Value accessed via (*ptrToRow): " << (*ptrToRow) << std::endl; // Output: 1 (dereference to get the first row, then index)
    std::cout << "Value accessed via *(*(ptrToRow) + 1): " << *(*(ptrToRow) + 1) << std::endl; // Output: 2 (Accesses multiArr[196])
    ptrToRow++; // Increment 'ptrToRow' to point to the next row (multiArr[196]) 
    std::cout << "Value accessed via ptrToRow after increment: " << ptrToRow << std::endl; // Output: 4
    return 0;
}

Output

--- Pointers and Arrays Relationship ---
Value of arr (using array indexing): 0x7ffdaf12e8a0
Value pointed to by arrPtr (dereferencing): 10
Accessing array elements using different notations:
arr[0] = 10
*(arr + 0) = 10
arrPtr[0] = 10
*(arrPtr + 0) = 10
Address of arr[0]: 0x7ffdaf12e8a0
Address (arr + 0): 0x7ffdaf12e8a0
Address (arrPtr + 0): 0x7ffdaf12e8a0
arr[1] = 20
*(arr + 1) = 20
arrPtr[1] = 20
*(arrPtr + 1) = 20
Address of arr[1]: 0x7ffdaf12e8a4
Address (arr + 1): 0x7ffdaf12e8a4
Address (arrPtr + 1): 0x7ffdaf12e8a4
arr[2] = 30
*(arr + 2) = 30
arrPtr[2] = 30
*(arrPtr + 2) = 30
Address of arr[2]: 0x7ffdaf12e8a8
Address (arr + 2): 0x7ffdaf12e8a8
Address (arrPtr + 2): 0x7ffdaf12e8a8
arr[3] = 40
*(arr + 3) = 40
arrPtr[3] = 40
*(arrPtr + 3) = 40
Address of arr[3]: 0x7ffdaf12e8ac
Address (arr + 3): 0x7ffdaf12e8ac
Address (arrPtr + 3): 0x7ffdaf12e8ac
arr[4] = 50
*(arr + 4) = 50
arrPtr[4] = 50
*(arrPtr + 4) = 50
Address of arr[4]: 0x7ffdaf12e8b0
Address (arr + 4): 0x7ffdaf12e8b0
Address (arrPtr + 4): 0x7ffdaf12e8b0
Initial value via currentPtr: 10
Value after currentPtr++: 20
Value after currentPtr += 2: 40
--- Multidimensional Arrays and Pointers ---
Value of multiArr: 0x7ffdaf12eba0
Value accessed via ptrToRow: 0x7ffdaf12eba0
Value accessed via (*ptrToRow): 0x7ffdaf12eba0
Value accessed via *(*(ptrToRow) + 1): 2
Value accessed via ptrToRow after increment: 0x7ffdaf12ee7c

Tips for Modern C++

Though powerful, built-in arrays and pointers are error-prone. Out-of-bounds or deallocated RAM can cause serious security vulnerabilities. Use std::vector or std::array instead of raw built-in arrays and pointers for most programming operations. Library classes abstract memory management and remove pointer concerns. In Chapter 6, Classes, and Chapter 12, Dynamic Memory, “smart pointers” like std::unique_ptr and std::shared_ptr are recommended for dynamically allocated memory since they rapidly cleanse memory via RAII.

Agarapu Geetha
Agarapu Geetha
My name is Agarapu Geetha, a B.Com graduate with a strong passion for technology and innovation. I work as a content writer at Govindhtech, where I dedicate myself to exploring and publishing the latest updates in the world of tech.
Index