- C Programming Tutorial
- C - Home
- Basics of C
- C - Overview
- C - Features
- C - History
- C - Environment Setup
- C - Program Structure
- C - Hello World
- C - Compilation Process
- C - Comments
- C - Tokens
- C - Keywords
- C - Identifiers
- C - User Input
- C - Basic Syntax
- C - Data Types
- C - Variables
- C - Integer Promotions
- C - Type Conversion
- C - Type Casting
- C - Booleans
- Constants and Literals in C
- C - Constants
- C - Literals
- C - Escape sequences
- C - Format Specifiers
- Operators in C
- C - Operators
- C - Arithmetic Operators
- C - Relational Operators
- C - Logical Operators
- C - Bitwise Operators
- C - Assignment Operators
- C - Unary Operators
- C - Increment and Decrement Operators
- C - Ternary Operator
- C - sizeof Operator
- C - Operator Precedence
- C - Misc Operators
- Decision Making in C
- C - Decision Making
- C - if statement
- C - if...else statement
- C - nested if statements
- C - switch statement
- C - nested switch statements
- Loops in C
- C - Loops
- C - While loop
- C - For loop
- C - Do...while loop
- C - Nested loop
- C - Infinite loop
- C - Break Statement
- C - Continue Statement
- C - goto Statement
- Functions in C
- C - Functions
- C - Main Function
- C - Function call by Value
- C - Function call by reference
- C - Nested Functions
- C - Variadic Functions
- C - User-Defined Functions
- C - Callback Function
- C - Return Statement
- C - Recursion
- Scope Rules in C
- C - Scope Rules
- C - Static Variables
- C - Global Variables
- Arrays in C
- C - Arrays
- C - Properties of Array
- C - Multi-Dimensional Arrays
- C - Passing Arrays to Function
- C - Return Array from Function
- C - Variable Length Arrays
- Pointers in C
- C - Pointers
- C - Pointers and Arrays
- C - Applications of Pointers
- C - Pointer Arithmetics
- C - Array of Pointers
- C - Pointer to Pointer
- C - Passing Pointers to Functions
- C - Return Pointer from Functions
- C - Function Pointers
- C - Pointer to an Array
- C - Pointers to Structures
- C - Chain of Pointers
- C - Pointer vs Array
- C - Character Pointers and Functions
- C - NULL Pointer
- C - void Pointer
- C - Dangling Pointers
- C - Dereference Pointer
- C - Near, Far and Huge Pointers
- C - Initialization of Pointer Arrays
- C - Pointers vs. Multi-dimensional Arrays
- Strings in C
- C - Strings
- C - Array of Strings
- C - Special Characters
- C Structures and Unions
- C - Structures
- C - Structures and Functions
- C - Arrays of Structures
- C - Self-Referential Structures
- C - Lookup Tables
- C - Dot (.) Operator
- C - Enumeration (or enum)
- C - Structure Padding and Packing
- C - Nested Structures
- C - Anonymous Structure and Union
- C - Unions
- C - Bit Fields
- C - Typedef
- File Handling in C
- C - Input & Output
- C - File I/O (File Handling)
- C Preprocessors
- C - Preprocessors
- C - Pragmas
- C - Preprocessor Operators
- C - Macros
- C - Header Files
- Memory Management in C
- C - Memory Management
- C - Memory Address
- C - Storage Classes
- Miscellaneous Topics
- C - Error Handling
- C - Variable Arguments
- C - Command Execution
- C - Math Functions
- C - Static Keyword
- C - Random Number Generation
- C - Command Line Arguments
- C Programming Resources
- C - Questions & Answers
- C - Quick Guide
- C - Cheat Sheet
- C - Useful Resources
- C - Discussion
Pointers and Multidimensional Arrays in C
In C language, an array is a collection of values of similar type stored in continuous memory locations. Each element in an array (one-dimensional or multi-dimensional) is identified by one or more unique integer indices.
A pointer, on the other hand, stores the address of a variable. The address of the 0th element in an array is the pointer of the array. You can use the "dereference operator" to access the value that a pointer refers to.
You can declare a one-dimensional, two-dimensional or multi-dimensional array in C. The term "dimension" refers to the number of indices required to identify an element in a collection.
Pointers and One-dimensional Arrays
In a one-dimensional array, each element is identified by a single integer:
int a[5] = {1, 2, 3, 4, 5};
Here, the number "1" is at the 0th index, "2" at index 1, and so on.
A variable that stores the address of 0th element is its pointer −
int *x = &a[0];
Simply, the name of the array too points to the address of the 0th element. So, you can also use this expression −
int *x = a;
Example
Since the value of the pointer increments by the size of the data type, "x++" moves the pointer to the next element in the array.
#include <stdio.h> int main(){ int arr[] = {1, 2, 3, 4, 5}; int length = sizeof(arr) / sizeof(arr[0]); int i = 0; int *ptr = arr; while (i < length){ printf("arr[%d]: %d \n", i, *(ptr + i)); i++; } return 0; }
Output
When you run this code, it will produce the following output −
arr[0]: 1 arr[1]: 2 arr[2]: 3 arr[3]: 4 arr[4]: 5
Pointers and Two-dimensional Arrays
If a one-dimensional array is like a list of elements, a two-dimensional array is like a table or a matrix.
The elements in a 2D array can be considered to be logically arranged in rows and columns. Hence, the location of any element is decided by two indices, its row number and column number. Both row and column indexes start from "0".
int arr[2][2];
Such an array is represented as −
Col0 | Col1 | Col2 | |
---|---|---|---|
Row0 | arr[0][0] | arr[0][1] | arr[0][2] |
Row1 | arr[1][0] | arr[1][1] | arr[1][2] |
Row2 | arr[2][0] | arr[2][1] | arr[2][2] |
It may be noted that the tabular arrangement is only a logical representation. The compiler allocates a block of continuous bytes. In C, the array allocation is done in a row-major manner, which means the elements are read into the array in a row−wise manner.
Here, we declare a 2D array with three rows and four columns (the number in the first square bracket always refers to the number of rows) as −
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
The compiler will allocate the memory for the above 2D array in a row−wise order. Assuming that the first element of the array is at the address 1000 and the size of type "int" is 4 bytes, the elements of the array will get the following allocated memory locations −
Row 0 | Row 1 | Row 2 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Value | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
Address | 1000 | 1004 | 1008 | 1012 | 1016 | 1020 | 1024 | 1028 | 1032 | 1036 | 1040 | 1044 |
We will assign the address of the first element of the array num to the pointer ptr using the address of & operator.
int *ptr = &arr[0][0];
Example 1
If the pointer is incremented by 1, it moves to the next address. All the 12 elements in the "3×4" array can be accessed in a loop as follows −
#include <stdio.h> int main(){ int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, }; // pointer ptr pointing at array num int *ptr = &arr[0][0]; int i, j, k = 0; // print the elements of the array num via pointer ptr for (i = 0; i < 3; i++){ for (j = 0; j < 4; j++){ printf("%d ", *(ptr + k)); k++; } printf("\n"); } return 0; }
Output
When you run this code, it will produce the following output −
1 2 3 4 5 6 7 8 9 10 11 12
In general, the address of any element of the array by with the use the following formula −
add of element at ith row and jth col = baseAddress + [(i * no_of_cols + j) * sizeof(array_type)]
In our 3×4 array,
add of arr[2][4] = 1000 + (2*4 + 2)*4 = 1044
You can refer to the above figure and it confirms that the address of "arr[3][4]" is 1044.
Example 2
Use the dereference pointer to fetch the value at the address. Let us use this formula to traverse the array with the help of its pointer −
#include <stdio.h> int main(){ // 2d array int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int ROWS = 3, COLS = 4; int i, j; // pointer int *ptr = &arr[0][0]; // print the element of the array via pointer ptr for (i = 0; i < ROWS; i++){ for (j = 0; j < COLS; j++) { printf("%4d ",*(ptr + (i * COLS + j))); } printf("\n"); } return 0; }
Output
When you run this code, it will produce the following output −
1 2 3 4 5 6 7 8 9 10 11 12
Pointers and Three-dimensional Arrays
A three-dimensional array is an array of two-dimensional arrays. Such an array is declared with three subscripts −
int arr [x] [y] [j];
This array can be considered as "x" number of layers of tables, each table having "x" rows and "y" number of columns.
An example of a 3D array is −
int arr[3][3][3] ={ { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} }, { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} }, { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} }, };
A pointer to the 3D array can be declared as −
int * ptr = &arr[0][0][0];
Knowing that, the name of the array itself is the address of 0th element, we can write the pointer of a 3D array as −
int * ptr = arr;
Each layer of "x" rows and "y" columns occupies −
x * y * sizeof(data_type)
Number of bytes. Assuming that the memory allocated to the 3D array "arr" as declared above starts from the address 1000, the second layer (with "i = 1") starts at 1000 + (3 × 3) × 4 = 1036 byte position.
ptr = Base address of 3D array arr
If JMAX is the number of rows and KMAX is the number of columns, then the address of the element at the 0th row and the 0th column of the 1st slice is −
arr[1][0][0] = ptr + (1 * JMAX * KMAX)
The formula to obtain the value of an element at the jth row and kth column of the ith slice can be given as −
arr[i][j][k] = *(ptr + (i * JMAX*KMAX) + (j*KMAX + k))
Example: Printing a 3D Array using Pointer Dereferencing
Let us use this formula to print the 3D array with the help of the pointer dereferencing −
#include <stdio.h> int main(){ int i, j, k; int arr[3][3][3] = { { {11, 12, 13}, {14, 15, 16}, {17, 18, 19} }, { {21, 22, 23}, {24, 25, 26}, {27, 28, 29} }, { {31, 32, 33}, {34, 35, 36}, {37, 38, 39} }, }; int JMAX = 3, KMAX = 3; int *ptr = arr; // &arr[0][0][0]; for(i = 0; i < 3; i++){ for(j = 0; j < 3; j++){ for(k = 0; k < 3; k++){ printf("%d ",*(ptr+(i*JMAX*KMAX)+(j*KMAX+k))); } printf("\n"); } printf("\n"); } return 0; }
Output
When you run this code, it will produce the following output −
11 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 28 29 31 32 33 34 35 36 37 38 39
In general, accessing an array with a pointer is quite similar to accessing an array with subscript representation. The main difference between the two is that the subscripted declaration of an array allocates the memory statically, whereas we can use pointers for dynamic memory allocation.
To pass a multi-dimensional array to a function, you need to use pointers instead of subscripts. However, using a subscripted array is more convenient than using pointers, which can be difficult for new learners.