How to use void pointer in C correctly?

Can someone explain why I am not getting the value of the variable, but its memory instead?

I need to use void * to indicate unsigned values.

As I understand the void pointers, their size is unknown, and their type is unknown.
After their initialization, they are known, right?

Why is my printf statement printing the wrong value?

#include <stdio.h> #include <stdlib.h> #include <string.h> void func(int a, void *res){ res = &a; printf("res = %d\n", *(int*)res); int b; b = * (int *) res; printf("b =%d\n", b); } int main (int argc, char* argv[]) { //trial 1 int a = 30; void *res = (int *)a; func(a, res); printf("result = %d\n", (int)res); //trial 2 unsigned short i = 90; res = &i; func(i, res); printf("result = %d\n", (unsigned short)res); return 0; } 

The output I get is:

 res = 30 b =30 result = 30 res = 90 b =90 result = 44974 
+4
source share
8 answers

Keep in mind: C does not guarantee that an int will be large enough to hold a pointer (including void* ). This casting is not a portable thing / good idea. Use the %p to printf pointer.

Similarly, you make a “bad throw” here: void* res = (int*) a tells the compiler: “I am sure that the value of a is a valid int* , so you should consider it as such.” If you really don't know that there is an int stored in memory address 30, this is not true.

Fortunately, you immediately overwrite res address of another a . (You have two vars named a and two named res , those specified in main and those specified in func . Which in func are copies of the value specified in main when you call it there.) Generally speaking overwriting the value of a function parameter is a "bad form", but it is technically legal. Personally, I recommend declaring all the parameters of your functions as const 99% of the time (for example, void func (const int a, const void* res) )

Then you added res to unsigned short . I don’t think anyone is still running on a 16-bit address space CPU (well, maybe Apple II), so this will definitely ruin the res value, truncating it.

In general, in C, type drives are dangerous. You overfill a system like a compiler and say: “Listen, Mr. Compiler, I am a programmer, and I know better than you what I have here. So, you just keep quiet and do it.” Casting with a pointer to a non-pointer type is almost universally erroneous. Casting between types of pointers is most often incorrect.

I would suggest checking out some of the Related links on this page to find a good overview of how C pointers in general work. Sometimes reading a few is required to really understand how this happens together.

+7
source
 (unsigned short)res 

- this is a cast to the pointer, res is the memory address, by discarding it in an unsigned short, you get the address value as an unsigned short instead of a hexadecimal value, to be sure that you get the correct value you can print

 *(unsigned short*)res 

The first listing (unsigned short*)res casts to void* pointer to a pointer to unsigned short . Then you can extract the value inside the memory address pointed to by res by dereferencing it with *

+6
source

The void pointer is used in C as a kind of generic pointer. The void pointer variable can be used to contain the address of any type of variable. The problem with the void pointer is that when you assigned an address to the pointer, the variable type information is no longer available to the compiler for verification.

In general, void pointers should be avoided, since the type of the variable whose address is in the void pointer is no longer available to the compiler. On the other hand, there are cases when the void pointer is very convenient. However, the programmer needs to know the type of variable whose address is in the void pointer variable and use it correctly.

Much of the C source code has a C-style created between type pointers and void pointers. This is not necessary for modern compilers, and should be avoided.

The size of the void pointer variable is known. The size of the variable whose pointer is in the void pointer variable is unknown. For example, here are some initial examples.

 // create several different kinds of variables int iValue; char aszString[6]; float fValue; int *pIvalue = &iValue; void *pVoid = 0; int iSize = sizeof(*pIvalue); // get size of what int pointer points to, an int int vSize = sizeof(*pVoid); // compile error, size of what void pointer points to is unknown int vSizeVar = sizeof(pVoid); // compiles fine size of void pointer is known pVoid = &iValue; // put the address of iValue into the void pointer variable pVoid = &aszString[0]; // put the address of char string into the void pointer variable pVoid = &fValue; // put the address of float into the void pointer variable pIvalue = &fValue; // compiler error, address of float into int pointer not allowed 

One way to use void pointers is to have several different types of structures that are provided as arguments to a function, usually some kind of dispatch function. Since the interface for the function allows different types of pointers, the void pointer must be used in the argument list. Then the type of the variable pointed to is determined either by an additional argument, or checks the specified variable. An example of such a use of a function is the following. In this case, we include a pointer to the type of structure in the first member of the various permutations of the structure. As long as all the structures that are used with this function have as their first member an int indicating the type of structure, this will work.

 struct struct_1 { int iClass; // struct type indicator. must always be first member of struct int iValue; }; struct struct_2 { int iClass; // struct type indicator. must always be first member of struct float fValue; }; void func2 (void *pStruct) { struct struct_1 *pStruct_1 = pStruct; struct struct_2 *pStruct_2 = pStruct; switch (pStruct_1->iClass) // this works because a struct is a kind of template or pattern for a memory location { case 1: // do things with pStruct_1 break; case 2: // do things with pStruct_2 break; default: break; } } void xfunc (void) { struct struct_1 myStruct_1 = {1, 37}; struct struct_2 myStruct_2 = {2, 755.37f}; func2 (&myStruct_1); func2 (&myStruct_2); } 

Something like the above has a number of problems with the design of communication and communication software, so if you have no good reason to use this approach, it is better to rethink your design. However, the C programming language allows you to do this.

There are some cases where a void pointer is required. For example, the malloc() function, which allocates memory, returns a void pointer containing the address of the region that was allocated (or NULL if the allocation fails). The void pointer in this case allows you to use one malloc() function, which can return the memory address for any type of variable. The following shows the use of malloc() with various types of variables.

 void yfunc (void) { int *pIvalue = malloc(sizeof(int)); char *paszStr = malloc(sizeof(char)*32); struct struct_1 *pStruct_1 = malloc (sizeof(*pStruct_1)); struct struct_2 *pStruct_2Array = malloc (sizeof(*pStruct_2Array)*21); pStruct_1->iClass = 1; pStruct_1->iValue = 23; func2(pStruct_1); // pStruct_1 is already a pointer so address of is not used { int i; for (i = 0; i < 21; i++) { pStruct_2Array[i].iClass = 2; pStruct_2Array[i].fValue = 123.33f; func2 (&pStruct_2Array[i]); // address of particular array element. could also use func2 (pStruct_2Array + i) } } free(pStruct_1); free(pStruct_2Array); // free the entire array which was allocated with single malloc() free(pIvalue); free(paszStr); } 
+1
source

If you need to pass the variable a by name and use it, try something like:

 void func(int* src) { printf( "%d\n", *src ); } 

If you get void* from a library function and know its actual type, you should immediately save it in a variable of the correct type:

 int *ap = calloc( 1, sizeof(int) ); 

There are several situations in which you should get the parameter by reference as void* , and then execute it. One of the most difficult situations in the real world is the flow procedure. So you can write something like:

 #include <stddef.h> #include <stdio.h> #include <pthread.h> void* thread_proc( void* arg ) { const int a = *(int*)arg; /** Alternatively, with no explicit casts: * const int* const p = arg; * const int a = *p; */ printf( "Daughter thread: %d\n", a ); fflush(stdout); /* If more than one thread outputs, should be atomic. */ return NULL; } int main(void) { int a = 1; const pthread_t tid = pthread_create( thread_proc, &a ); pthread_join(tid, NULL); return EXIT_SUCCESS; } 

If you want to live in danger, you can pass a uintptr_t value other than void* and drop it, but beware of traps.

+1
source

printf("result = %d\n", (int)res); prints the res value (pointer) as a number. Remember that a pointer is an address in memory, so it will print some random 32-bit number.

If you want to print the value stored at this address, then you need (int) * res - although (int) is not needed.

edit: if you want to print the value (i.e. address) of the pointer, then you should use %p , essentially the same thing, but format it better and understand if the sizes of int and poitner are different on your platform

0
source

If you have a void ptr , which, as you know, points to an int , to access this int write:

 int i = *(int*)ptr; 

That is, first pass it to a pointer-to-int with the cast (int*) operator, and then search for it to get the specified value.

You are hovering directly over the value type, and although the compiler would happily do this, it might not be what you want.

0
source
 void *res = (int *)a; 

a is int, but not ptr, maybe it should be:

 void *res = &a; 
0
source

The size of the void pointer is known; this is the size of the address, so the same size as any other pointer. You are freely converting between integer and pointer, and this is dangerous. If you want to take the address of the variable a , you need to convert its address to void * with (void *)&a .

0
source

Source: https://habr.com/ru/post/1385566/


All Articles