In this article, we will discuss below topics
- void pointer Basics
- How to Dereferencing a void pointer in C
- size of a void pointer
- Typecast to different datatypes
- void pointer to structure
- Structure member is void pointer
- void pointer to different structures
- void pointer to an array
- Function arguments are void pointer
- Function return type is void pointer
- void pointer to the array of structures
- Array of void pointer
- Embedded system example of void pointer
===============================================================================================
By definition, Pointer is used to store address of any variable or function, array, structure but we need to remember that types of the pointer should be the same as the types of the pointed object (variable, pointer, array, function …etc.).
for example int *ptr; can holds the address of integer variable.
int a=10; ptr=&a; it is possible because pointer variable is integer type.
float b=10.5; ptr=&b; it is not possible because pointer variable is integer type but address assigned with float type.
Look into the below program
variable "b" is float type and assigned for different pointer type(int, float)
we can see warning: assignment to ‘int *’ from incompatible pointer type ‘float *
- int* ptr_int; ptr_int=&b; gives the warning and if you try to deference the value, it produces the wrong output.
- float *ptr_float; ptr_float=&b; it gives the proper output during our pointer-dereference.
To resolve above problem, C-programmers are using void pointer concept.
By definition, A void pointer is a pointer that has no associated data type with it. A void pointer can hold address of any type and can be typecasted to any type.
Look into the below program,
This program resolved the problem in previous program by using void pointer and typecast method.
- void* ptr; is the void pointer
- ptr=&a; assigned the address of integer variable and deferenced by "*(int*)ptr" typecast is (int*)
- ptr=&b; assigned the address of float variable and deferenced by "*(float*)ptr" typecast is (float*)
In case of void pointer we cannot use the indirection operator directly. This is because a void pointer has no data type associated with it. there is no datatype associated hence it creates a problem for the compiler to predict the size of the pointed object. So before dereferencing the void pointer, we have to typecast it.
typecast inform to the compiler that "How many byte of data should be reserved for the variable".
Look into below program: we are not able to get the value of "a" variable by using Indirection operator(*). so while deferencing, we need to do typecast.
*ptr gives an error because you are trying to access value in the void pointer address, compiler doesn't know what type of value need to be printed.
Just typecast, what will happen? (int*)ptr acts as a integer pointer. you see below program address of "a" and "(int*)ptr" both are giving same address.
So, we use indirection operator (*) to deference the value. *(int*)ptr is the right way to Dereferencing a void pointer in C.
Size of the pointer variable is platform dependent. size of the void pointer(void*) also platform dependent. typically 4-bytes for 32-bit platform and 8-bytes for 64-bit platform.
Look into below program, it shows the difference between pointer size and without pointer size.
- Character is 1-byte but character pointer is 8-byte
- Structure is 32-byte but structure pointer is 8-byte According to C standard, the pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
Typecast to different datatypes
Look into below program, we typecasted integer and char types to void pointer. Here we need to check the values that are printed for "int and char".
In the above program, Char values are overflowed because integer has 4 bytes but char has only one byte.
Note: The char type takes 1 byte of memory (8 bits) and allows expressing in the binary notation 2^8=256 values. The char type can contain both positive and negative values. The range of values is from -128 to 127.
Caution: programmer should know data ranges of each datatype before typecast.
void pointer to structure
In the below program, three concepts are covered.
- Programmer get confused many times about "pointer value increment" and "pointer address increment".
- *(int*)ptr+1 not same as *((int*)ptr+1), look into the number of brackets or Parentheses used. *(int*)ptr+1 means add 1 to the value present in ptr. Parentheses and Dereference(* ) has high priority so compiler gets the value 5, later add 1 to it hence value is 6.
- ((int*)ptr+1) is same as ptr[1]. *ptr[1] is value in that location. here Parentheses are covered ptr and 1 so it is represents the array index "1". hence it is deference the value in the 1st index value.
- if you have same types of structure members, you can access by pointer address increment
- there is no difference if the structure having same types of members and array.
I applied the same logic like pointer address increment to dissimilar data members but dissimilar types are not produced proper output.
- void* ptr; void pointer declared.
- mystruct M1={10, 20}; declared structure variable M1 and initialized the structure members.
- ptr=&M1; we assigned address of structure variable "M1"
- (mystruct*)ptr->a; we are think that here is we assigned structure address and void pointer variable holds the address of structure so we can access struct members but it is not correct from compiler side. (Figure-2)
Look into the below two programs,
Figure-1: wrong output by "increment the pointer address"
- ptr=&M1; wrong way to inform the compiler about the structure address.
- ptr=(mystruct*)&M1; we should points to the structure and assign the structure member address.
Look into below program, we resolved void pointer to structure issue.
It is simple and also same as void pointer to the normal member. here our structure member is void pointer.
void pointer to different structures
In this method, we are assigning different structures to the void pointer. every time referencing to the different structures so we need to inform compiler which structure address is assigning.
- First time: ptr=(mystruct1*)&M1; first struct address is referred.
- Second time: ptr=(mystruct2*)&M2; second struct address is referred.
void pointer to an array
This topic already discussed in the structure of similar elements.
In this program, we used malloc for memory assignment and we used different array for the void pointer.
we dereference by using ((int*)ptr+i). Initially I thought that we can use ((int*)ptr[i]) to deference the values but here array subscript and parenthesis having same priority so associativity is affecting.
compiler first evaluates the array subscript hence compiler does not predict the datatype of the variable.
In this below program, we discussing how to pass different datatypes to function arguments.
- Function declaration: We have function with function arguments are void pointers "int Comparator(void*, void*, int);". here two arguments are void pointers so programmer can send any type of data to void pointers but programmer should inform to compiler about what type of data they need to be sent before pass to function.
- Function call: we called three functions with different types of data.
- int res=Comparator((int*)&x, (int*)&y, 0); pass integer data to void pointer in function.
- int res1=Comparator((char**)&name, (char**)&alpha, 1); pass string (character pointer) to to void pointer in function.
- int res2=Comparator(ptr1, ptr2, 2); pass structure variable to void pointer in function.
- Function definition: "int Comparator(void* arg1, void* arg2, int select) { function body}". here "arg1, arg2" receives the address of variable while deference again inform compiler about datatype.
In the below program, we are discussing about void pointer return type from function. function is returned different data like int , float.
Same function declaration used for "two integer numbers addition" and "addition of two float numbers" finally function return int and float address according to function selection.
- Function declaration: void* generic_func(void*, void*, int); here void pointer is return type. function accepts the different data address.
- Function call:
- generic_func((int*)&a, (int*)&b, 0); for integer address return type
- generic_func((float*)&c, (float*)&d, 1); for float address return type
- Function definition: void* generic_func(void* x, void* y, int select){function body} here each function call returned different addresses.
This topic is same as array to void pointer. in this program we are declared that array of structures and dereferenced by using arrow operator.
Look into below program
- structure is "mystruct" with two members
- declared void pointer void* ptr; and array of structure variables are declared by using "mystruct".
- mystruct Select1[3]={{5,6.5},{6, 8.25},{9, 3.45}};
- ptr=(mystruct*)&Select1; structure address is assigned to void pointer.
- dereference is done " ((mystruct*)ptr+<array Index>)->a".
In this section, we will discuss about an array of void pointer and dereference the value and also pass to function as an argument.
- declaration: void* ptr[3]; we declared array of size 3. so we can assign three different data to void pointer. i.e.., ptr[0]=(int*)&a; ptr[1]=(float*)&b; ptr[2]=(char**)&name;
- dereference : we dereference the values by referring to array subscript *(int*)ptr[0]. Note that don't confuse with "void pointer to array" because there we used pointer address increment.
- void pointer to array; void *ptr; int a[3]={2,4,6}; ptr=&a; here void pointer is scalar and address of array is assigned to pointer.
- array of void pointer: void *ptr[3]; ptr[0]=(int*)&a; ptr[1]=(float*)&b; here void pointer is an array so each index is assigned with different data addresses.
Embedded example of void pointer
In the below we implemented two counter handles.
each handle is separately increment and reset the value according to user call.
========================================================================================================
Some of the topics like Structure member is void pointer of function pointer ,void pointer to the function pointer ,void pointer to the function pointer array not directly supported by C-Standard.
we will discuss when we come-cross an real-time application.
Thanks for visiting the post..!!
========================================================================================================
No comments:
Post a Comment