Void Pointer
On different system, the size of the pointer can vary. Also on different data type that the pointer points to, the size can vary.
Therefore you can run into the trouble of assigning various type of other pointers to different type.
As a result, C
provides a pointer of type (void*)
void *ptr
This can be use to point to any object of any data type.
For example
#include <stdio.h>
int main() {
int array[] = {9,2,3,4};
void *ptr = array;
printf("ptr: %p,value ptr: %d\n", ptr, *((int*) ptr));
}
In here, to read the value of array
(Pointer and Array) which is the first element of the array, we need to cast it to (int*)
pointer and then dereference.
As a result, it will give us value 9
.
ptr: 0x16dcbad90, value ptr: 9
Arithmetic
If we declare our pointer as void *
, when doing Pointer Arithmetic, for example
#include <stdio.h>
int main() {
int array[] = {4129,2,3,4};
void *ptr = array;
printf("ptr: %p, nextPtr: %p\n", ptr, ptr + 1);
}
Since the type of the pointer is undefine, it default to char
pointer. Therefore, we only add 1
to the pointer. For example:
ptr: 0x16fdbad90, nextPtr: 0x16fdbad91
BONUS: What happen if you dereference this value?
Since 4129
in heximal would be
Address | 0 | 1 | 2 | 3 |
---|---|---|---|---|
Data | 21 | 10 | 00 | 00 |
0x16fdbad91
would try to dereference from 10 + next 4 bytes
and lead to unexpected value.
#include <stdio.h>
int main() {
int array[] = {4129,2,3,4};
void *ptr = array;
void *nPtr = ptr + 1;
printf("ptr: %p, nPtr: %p, nextPtrValue: %d\n", ptr, nPtr, *((int*) nPtr));
}
ptr: 0x16f43ad90, nPtr: 0x16f43ad91, nextPtrValue: 33554448
As a result, we can see that it tries to make 33554448
which is in heximal:
Address | 0 | 1 | 2 | 3 |
---|---|---|---|---|
Data | 10 | 00 | 00 | 02 |
Which started at 10
and the next value will overlap 2
(the second element in the array) which has the heximal of 02 00 00 00
Explain
So in total, consider the first 2 values {4129, 2}
we have the memory looking like this:
Address | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
Data | 21 | 10 | 00 | 00 | 02 | 00 | 00 | 00 |
Which:
- the first
4
address (0x00001021
) will be4129
- the next
4
address (0x00000002
) will be2
In [10]: int("00001021",16)
Out[10]: 4129
In [11]: int("00000002",16)
Out[11]: 2
Therefore, when (0x16f43ad91
) — which start from address 1
trying to dereference as int
, it will try to read the next 4 bytes from address 1
.
Which is:
Address | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Data | 10 | 00 | 00 | 02 |
Which is 0x02000010
in heximal. When converting it to int
, we have
In [12]: int("02000010",16)
Out[12]: 33554448