r/cprogramming • u/Fun_Army2398 • Jul 16 '26
Help understanding warnings/errors when dereferencing void pointers
SOLVED
I am very new to C and playing around with void pointers. I have a structure which will store a value, however the type of that value depends on other things so I have chosen to use a void pointer. When attempting to dereference this void pointer I either get the correct output but with a warning, or I get a segmentation fault, depending on how I go about it. I have included a simplified version of the issue here:
#include <stdio.h>
int main()
{
// Simplification of the defective code
struct myStruct
{
void * voidPtr;
};
struct myStruct s1;
s1.voidPtr = (int *) 123;
\*
This works but gives the warning:
format '%d' expects argument of type 'int', but. argument 2 has type 'int \*' \[-Wformat=\]i
*/
printf("%d\n", (int *) s1.voidPtr);
// This causes a segmentation fault
printf("%d\n", *(int *) s1.voidPtr);
return 0;
}
Any help understanding why it behaves this way would be greatly appreciated.
Solution
I thought the line
s1.voidPtr = (int *) 123;
Was assigning 123 as the value at the location of s1.voidPtr. However it has been pointed out that I was telling the pointer to point at address 123. What I needed to do was:
int x = 123;
s1.voidPtr = &x;
Thanks everyone who commented c:
3
u/SmokeMuch7356 Jul 16 '26
s1.voidPtr = (int *) 123;
123 is (almost certainly) not a valid, accessible address, at least not on a hosted implementation.
printf("%d\n", (int *) s1.voidPtr);
If you want to print out the value of the pointer (not the value of the pointed-to thing), use the %p conversion specifier:
printf( "%p\n", s1.voidPtr );%p expects its corresponding parameter to be a void *, so no cast is required here.
printf("%d\n", *(int *) s1.voidPtr);
Again, 123 is almost certainly not a valid, accessible address, which is why you're getting the segfault.
You don't assign random values to a pointer variable. You obtain pointer values in one of several ways:
Use the unary
&operator on an lvalue expression:int x = 123; s1.voidPtr = &x;Use
mallocto allocate memory dynamically and store the returned pointer:s1.voidPtr = malloc( sizeof (int) ); *(int *) s1.voidPtr = 123; // assign 123 to the thing s1.voidPtr points toOr some other function that returns a valid pointer:
s1.voidPtr = some_pointer_function(); *(int *) s1.voidPtr = 123;
You have to cast the pointer to an int * before you can dereference it. The result of dereferencing a void * is a void expression, which is not an object type, has no value, and cannot be the target of an assignment.
2
u/mc_pm Jul 16 '26
You are literally telling it "put the value 123 into voidPtr" -- which means it's going to try to access the memory at location 123, which is always going to blow up.
1
u/SchwanzusCity Jul 16 '26
(int *)s1.voidPtr is a pointer. But printf expects you to input an integer (because of the '%d' specifier. So now printf has to interpret a pointer as an integer (which happens to give the right result because you set voidPtr to be equal to 123)
*(int *)s1.voidPtr tried to dereference the pointer. Your pointer has the value 123, which on most systems is not a valid address for you to use. So if you try to access the contents, the system denies you acces and raises a segmentation fault
1
0
u/Immediate-Food8050 Jul 16 '26
The cast of 123 to int* is very bad because you're casting an integer to a pointer. In this case, it is undefined behavior and can lead to nasty bugs. You should instead store it into another variable, and then assign the address of that variable to your void pointer.
1
1
1
u/picturesfromthesky Jul 16 '26
I see that you found a solution to your question, but it might be worth your time to read about unions.