Pointers in C are variables that can store memory addresses. This feature allows them to have a wide range of applications, such as holding addresses of variables, arrays, structures, and even other pointers. When a pointer is pointing to a variable, it means it’s holding the address of that variable. Pointers play a crucial role in C as they enable us to traverse and retrieve data from any memory location. However, they can be complex to handle and understand. In this explanation, we aim to simplify the concept of pointers in C, retaining the key points.
Pointer holding address of a variable:
Declaring a Pointer
int *iptr; // integer pointer
char *cptr; // character pointer
float *fptr; // float pointer
Depends on the type of data present in a memory location the type of pointer is determined.
Assignment of a pointer
int a = 10;
int *ptr = &a; //assignment at the time of declaration
int a = 10;
int *ptr;
ptr = &a; // assigning a variable address to a pointer
char ch = 'A';
char *ptr = &a; // assigning a character variable
When the address of a variable is assigned to a pointer, the pointer stores the base or starting address of that variable. For example, if an integer variable a occupies memory locations 0x1000, 0x1001, 0x1002, and 0x1003, assigning its address to a pointer will cause the pointer to store the address 0x1000. Similarly, if a character variable is stored at memory location 0x3010, its pointer will hold the address 0x3010.
Dereferencing a Pointer
Dereferencing a pointer involves accessing the value stored at the memory location that the pointer is pointing to. This can be done using the * operator in front of the pointer variable.
int main()
{
int a = 10;
int *iptr = &a;
printf("The value at memory location %p is %d\n", iptr, *iptr);
}
output
The value at memory location 12efed4 is 10
Note: address values are not same everytime.
char ch = 'a';
char *cptr = &ch;
printf("the value at memory location %p is %c\n", cptr, *cptr);
output
The value at memory location a56efff23 is a;
When a pointer is dereferenced, the amount of data it reads from memory depends on its type. For example, an integer pointer reads 4 bytes of data starting from the address it holds, while a character pointer reads only 1 byte. This is why the type of a pointer should generally match the type of the variable it points to.
However, there are situations where assigning a pointer to a variable of a different type can be useful. Consider the following example:
int a = 0x123456789;
char *ptr = (char *)&a;
printf("Data at LSB = %x\n", *ptr);
In this code:
ptr
is a character pointer, which means it will only read 1 byte of data when dereferenced.- Since
ptr
holds the starting address of the integera
, dereferencingptr
will give us the least significant byte (LSB) ofa
.
If the output is 89
, it indicates that the system is little-endian, meaning the LSB is stored at the lower memory address. If the output is 12
, the system is big-endian, where the most significant byte (MSB) is stored at the lower memory address.
Another interesting use case of a pointer is to determine whether the system is 32-bit or 64-bit. In a 32-bit system, 4 bytes of memory are sufficient to store 32-bit address values. In contrast, a 64-bit system requires 8 bytes to store 64-bit address values. By using sizeof(ptr)
, you can find out the size of a pointer and thus determine whether the system is 32-bit or 64-bit. If sizeof(ptr)
returns 4, the system is 32-bit; if it returns 8, the system is 64-bit.
sample program
#include <stdio.h>
int main()
{
int a = 30;
int *ptr = &a;
printf("The value of a is %d\n", a);
printf("ptr is pointing to the value: %d\n", *ptr);
printf("the location of variable a is:%p\n", ptr);
}
output:
The value of a is 30
ptr is pointing to the value: 30
the location of variable a is:0x7ffe81ad3e6c
Lets have a look for character variable:
#include <stdio.h>
int main()
{
char a = 'Z';
char *ptr = &a;
printf("The value of a is %c\n", a);
printf("ptr is pointing to the value: %c\n", *ptr);
printf("the location of variable a is:%p\n", ptr);
}
output:
The value of a is Z
ptr is pointing to the value: Z
the location of variable a is:0x7ffcff8225ef
Arithmetic of pointers
We have seen that the amount of data a pointer reads depends on its type; similarly, the result of arithmetic operations on a pointer is also based on its type. For example, when a character pointer is incremented, its address value increases by 1, meaning it now points to the next memory location. On the other hand, when an integer pointer is incremented, its address value increases by 4, so the pointer now holds the memory location 4 bytes ahead.
sample program to understand pointer arthimetic
#include <stdio.h>
#include <string.h>
int main()
{
int a = 10;
char ch = 'X';
long int l = 1947;
int *iptr = &a;
char *cptr = &ch;
long int *lptr = &l;
printf("a = %d, iptr = %p, *iptr = %d\n", a, iptr, *iptr);
printf("ch = %c, cptr = %p, *cptr = %c\n", ch, cptr, *cptr);
printf("l = %ld, lptr = %p, *lptr = %ld\n", l, lptr, *lptr);
iptr++;
cptr++;
lptr++;
printf("pointers after increment\n");
printf("iptr = %p\n", iptr);
printf("cptr = %p\n", cptr);
printf("lptr = %p\n", lptr);
}
output:
a = 10, iptr = 0x7fffffffdca4, *iptr = 10
ch = X, cptr = 0x7fffffffdca3, *cptr = X
l = 1947, lptr = 0x7fffffffdca8, *lptr = 1947
pointers after increment
iptr = 0x7fffffffdca8
cptr = 0x7fffffffdca4
lptr = 0x7fffffffdcb0
Valid pointer arithmetic operations in C
- addition of pointer with an interger (ptr + i) , incrementing (ptr++).
- subtraction of pointer with an integer (ptr – i), decrementing (ptr–), subtraction of two pointers of same type (ptr1 – ptr2).
Invalid pointer arithmetic operations in C
- addition of two pointers
- any multiplication operation with pointer.
- any division operation with pointer.
Prev << Loops in C
Next >> Endianess