Before we understand the relationship between pointers and arrays, let us see some basic examples of arrays.
Statically allocated arrays
The size of the array known at compile time is called as statically allocated arrays.
The memory will be given in the program stack.
They are stored in contiguous memory locations. Hence you can do pointer arithmetic to iterate over the elements.
Example:
1-D array:
int arr[5]; // declare a static array of 5 ints
char c_arr[5]; // declare a static array of 5 character
How to access array elements?
You can access array elements by using indexing as shown below:
#include<stdio.h>
void access_array(int *arr, int len)
{
for (int i = 0; i < len; ++i)
{
printf("arr[%d] = %d\n ", i, arr[i]);
}
}
int main ()
{
int array[5] = {1, 2, 3, 4, 5};
access_array(array, 5);
}
Output:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
How to access array elements using pointer arithmetic ?
WKT the array name holds the address of the first element of the array.
So when we do “ptr = arr”, then the pointer “ptr” will hold the address of the first element of the array.
Similarly “ptr + 1” will point to the next element of the array.
Example:
#include<stdio.h>
int main ()
{
int array[5] = {1, 2, 3, 4, 5};
int *ptr = array;
for (int i = 0; i < 5; ++i)
{
printf("&array[%d] = %u\t array[%d] = %d\n",i,ptr+i,i,*(ptr+i));
}
}
Output:
&array[0] = 4008389152 array[0] = 1
&array[1] = 4008389156 array[1] = 2
&array[2] = 4008389160 array[2] = 3
&array[3] = 4008389164 array[3] = 4
&array[4] = 4008389168 array[4] = 5
Dynamically allocated arrays
If the memory allocated at run time is called as dynamically allocated arrays. It is stored in heap.
To create dynamically allocated arrays, you need to call “malloc”.
Example:
#include<stdio.h>
#include<stdlib.h>
int main ()
{
int n = 5;
int *array = (int*) malloc(sizeof(int) * n);
for (int i = 0; i < n; ++i)
{
array[i] = i;
}
for (int i = 0; i < 5; ++i)
{
printf("&array[%d] = %u\t array[%d] = %d\n",i,array+i,i,*(array+i));
}
}
Output:
&array[0] = 3871365200 array[0] = 0
&array[1] = 3871365204 array[1] = 1
&array[2] = 3871365208 array[2] = 2
&array[3] = 3871365212 array[3] = 3
&array[4] = 3871365216 array[4] = 4
Pointers and arrays in c
Most of the coders who are beginners in programming, they will see the statement “ptr = arr;” and think that array and pointers are interchangeable.
This understanding is wrong. Although an array can be treated as a pointer at given times, but they cannot be interchanged.
In series of examples, we shall understand the difference between arrays and pointers.
Is char arr[] and char *a are identical to each other?
No they are different.
When you do “char arr[] = “hello”; ” space for 6 characters (including NULL terminating) is set aside, and the address of “h” is copied to “arr”. If it is a local variable, then it is stored in stack. Else if it is global variable, then it is stored in program bss segment. If it is dynamically created array, then it will be stored in heap segment.
When you do “char *ptr = “hello world”; “, “ptr” will be stored in stack segment. But “hello world” will be stored in the read only segment, and the address of it will be stored in ptr. Any operations to modify the data pointed by “ptr” is an undefined behavior.
So when are array and pointer declarations can be interchanged?
They can be interchanged when sending array as a function parameters.
Since array decay immediately into pointer, sometimes we can interchange the notation.
For example:
If a function is receiving an array as a parameter, the declaration of the function can be:
void fun(char arr[]) {
....
}
This can be written as below,
void fun(char *arr) {
....
}
what is the difference between “array”, “&array” ?
Consider the below example and o/p:
#include<stdio.h>
int main ()
{
int array[5] = {0};
printf("array = %p \n", array);
printf("&array = %p \n", &array);
return 0;
}
Output:
array = 3876039200
&array = 3876039200
From the above o/p we can see that both “array” and “&array” return the same address. So we might think both are same?
Are they same? No.
We will increment the array by 1 and perform pointer arithmetic.
Consider the below example:
#include<stdio.h>
int main ()
{
int array[5] = {0};
printf("array = %u, &array = %u \n", array, &array);
printf("array+1 = %u, &array+1 = %u \n", array+1, &array+1);
return 0;
}
Output:
array = 3906214432, &array = 3906214432
array+1 = 3906214436, &array+1 = 3906214452
As you can see “array + 1” has jumped 4 bytes.
As you can see “&array + 1” has jumped 20 bytes.
So it means, “array” is pointing to the first element of the array.
“&array” is pointing to the whole array of 5 int. So when you do “&array + 1” it will do “4 * 5 = 20”
what is the difference between arrays ad pointers in C?
Pointers are used to store the address of dynamically created arrays.
Pointers are used to store the address of array which are passed as arguments to functions.
Except above 2 statements, pointers and arrays are totally different.
Array name will give the address of the first element of the array.
Array elements can be accessed with the help of pointer arithmetic
#include<stdio.h>
#include<stdlib.h>
int main ()
{
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
printf("arr[2] = %d\n", arr[2]);
printf("*(arr + 2) = %d\n", *(arr + 2));
printf("ptr[2] = %d\n", ptr[2]);
printf("*(ptr + 2) = %d\n", *(ptr + 2));
return 0;
}
Output:
arr[2] = 3
*(arr + 2) = 3
ptr[2] = 3
*(ptr + 2) = 3
Array parameters are always passed as pointers even when we use square braces.
#include<stdio.h>
#include<stdlib.h>
int fun(int ptr[])
{
int x = 10;
printf("sizeof(ptr) = %d\n", sizeof(ptr));
ptr = &x;
printf("*ptr = %d ", *ptr);
return 0;
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
fun(arr);
return 0;
}
Output:
sizeof(ptr) = 8
*ptr = 10
How to declare and use array of pointers in C?
Just like a normal array that holds the data, instead of that, if the array holds the address of other variables is called as array of pointers.
Syntax:
data_type *array_name[size];
Example:
int *array_ptr [5];
Simple example:
In the below example, the array_ptr is holding the address of 5 variables.
Then we pint the value by dereferencing it.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *array_ptr[5];
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int i = 0;
array_ptr[0] = &a;
array_ptr[1] = &b;
array_ptr[2] = &c;
array_ptr[3] = &d;
array_ptr[4] = &e;
for(i = 0; i < 5; i++)
{
printf("Address = %u\t Value = %d\n", array_ptr[i], *array_ptr[i]);
}
return 0;
}
Output:
Address = 3926391304 Value = 1
Address = 3926391300 Value = 2
Address = 3926391296 Value = 3
Address = 3926391292 Value = 4
Address = 3926391288 Value = 5
How to pass 2D array as a function parameter?
There are different ways to pass 2D array as function parameter
Method 1:
Declare both the dimensions globally and send it.
#include<stdio.h>
#include<stdlib.h>
const int M = 3;
const int N = 3;
void display(int arr[M][N])
{
int i, j;
for (i = 0; i < M; i++)
for (j = 0; j < N; j++)
printf("%d ", arr[i][j]);
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
display(arr);
return 0;
}
Method 2:
You can also send variable sized array by specifying the variable dimension:
#include<stdio.h>
#include<stdlib.h>
const int M = 3;
const int N = 3;
void display(int m, int n, int arr[][n])
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", arr[i][j]);
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;
display(m, n, arr);
return 0;
}
Method 3:
By using single pointer:
#include<stdio.h>
#include<stdlib.h>
void display(int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
}
int main()
{
int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int m = 3, n = 3;
display(&arr[0][0], m, n);
return 0;
}