Problem using void pointer as a function argument - c

I can't understand this result...
The code:
void foo(void * key, size_t key_sz) {
HashItem *item = malloc(sizeof(HashItem));
printf("[%d]\n", (int)key);
...
item->key = malloc(key_sz);
memcpy(item->key, key, key_sz);
}
void bar(int num) {
foo(&num, sizeof(int));
}
And I do this call: bar(900011009);
But the printf() output is:
[-1074593956]
I really need key to be a void pointer, how can I fix this?

I think you need this:
printf("[%d]\n", *(int*)key);
The key is a void pointer to the int, so you first need to cast to an int pointer, then dereference to get the original int.

If you cast the pointer to int, you are getting the address as the value. You need to dereference void pointers like any other. Only you cannot directly dereference void *, so you must first cast it to a pointer of the correct type, here int *. Then dereference that pointer, i.e. *((int *)key) (extra parentheses to clarify the precedence).

Related

why trying to deference void pointer does not work?

int main()
{
int b = 12;
void *ptr = &b;
printf("%d", *ptr);
return 0;
}
I expected for this code to print 12, but it does not.
if instead of void pointer, we define int pointer it would work.
I wanted to know how can we use void pointer and print the address allocated to it and the amount saved in it?
Dereferencing a void * doesn't make sense because it has no way of knowing the type of the memory it points to.
You would need to cast to pointer to a int * and then dereference it.
printf("%d", *((int *)ptr));
void pointers cannot be dereferenced.it will give this warning
Compiler Error: 'void' is not a pointer-to-object type*
so, you have to do it like this.
#include<stdio.h>
int main()
{
int b = 12;
void *ptr = &b;
printf("%d", *(int *)ptr);
return 0;
}
If p has type void *, then the expression *p has type void, which means "no value". You can't pass a void expression to printf for the %d conversion specifier (or any other conversion specifier).
In order to dereference a void *, you must first convert it to a pointer of the appropriate type. You can do it with a cast:
printf( "%d\n", *(int *) ptr );
or assign it to a pointer of the appropriate type:
int *p = ptr;
printf( "%d\n", *p );
The rules around void pointers are special such that they can be assigned to other pointer types without an explicit cast - this allows them to be used as a "generic" pointer type. However, you cannot directly examine the thing a void pointer points to.
A schoolbook example of when void pointers are useful is qsort.
This is the signature:
void qsort(void *base,
size_t nitems,
size_t size,
int (*compar)(const void *, const void*)
);
base is just a pointer to the first element. The reason it's a void pointer is because qsort can be used for any list, regardless of type. nitems is number of items (doh) in the list, and size is the size of each element. Nothing strange so far.
But it does also take a fourth argument, which is a function pointer. You're supposed to write a custom compare function and pass a pointer to this function. This is what makes qsort able to sort any list. But since it's supposed to be generic, it takes two void pointers as argument. Here is an example of such a compare function, which is a bit bloated for clarity:
int cmpfloat(const void *a, const void *b) {
const float *aa = (float*) a;
const float *bb = (float*) b;
if(*aa == *bb) {
return 0;
} else if(*aa > *bb) {
return 1;
} else {
return -1;
}
}
Pretty clear what is going on. It returns positive number if a>b, zero if they are equal and negative if b>a, which is the requirements. In reality, I'd just write it like this:
int cmpfloat(const void *a, const void *b) {
return *(float*)a - *(float*)b;
}
What you do with this is something like:
float arr[5] = {5.1, 3.4, 8.9, 3.4, 1.3};
qsort(arr, 5, sizeof *arr, cmpfloat);
Maybe it's not completely accurate to say that void pointers are used instead of templates, generic functions, overloaded functions and such, but they have similarities.

Converting a int pointer to a void pointer and back to use the value in another function?

I would like to convert a int pointer to a void pointer and pass that void pointer to a function and then back to an int pointer to use that value in another function.
void main(){
int newSize = size;
void *newSizePtr = &newSize;
someFunc(newSizePtr);
}
void someFunc(void *newSizePtr){
int actualValue = *((int *) newSizePtr);
}
Is this the right way to convert a int ptr to a void ptr and then back to use the value?
i am unable to dynamically allocate memory to the pointer itself because of restrictions with my program that i cannot use malloc. i.e.
int *newSize = malloc(sizeof(int));
which is why i did it this way.
i also need to pass in a void* argument because in my program i am using pthread_create(). This function requires me to pass in an argument of a void* to the function which is why i casted it to a void* and then back when i needed to use it
The conversion you are doing is explicitly allowed by the C standard. Section 6.3.2.3p1 regarding pointer conversions states:
A pointer to void may be converted to or from a pointer to any
object type. A pointer toa ny object type may be converted to a
pointer to void and back again; the result shall compare equal
to the original pointer.
It's also not necessary to explictily cast to or from a void *. So you can do something like this:
void someFunc(void *newSizePtr){
int *actualValuePtr = newSizePtr;
}
int main(){
int newSize = size;
pthread_t tid;
pthread_create(&tid, NULL, someFunc, &newSize);
}
#include <stdio.h>
#include <memory>
void someFunc(void*);
int main() {
int size = 4;
int newSize = size;
void* newSizePtr = &newSize;
someFunc(newSizePtr);
// void* -> int*, before using
int* newSize = (int*) malloc(sizeof(int));
}
void someFunc(void* newSizePtr) {
int actualValue = *((int*)newSizePtr);
printf("%d", actualValue);
}
Yes you can cast void* to int*, and int* to void *,
Because, void * is 'generic' pointer.
malloc returns generic pointer (void*) because malloc does not know what 'type' of return you need.
So, you need to convert to the type you need.
(In the above code, you need to convert to void* -> int*)
For more information about usage of generic pointer, below link may help you
https://codexpart.com/what-is-generic-pointer-difference-between-generic-pointer-and-void-pointer/

Assignment from void pointer to another void pointer

I want to copy the bits from one void * to another void *.
How can I do it?
I tried this:
static void* copyBlock(void* ptr) {
if (!ptr) {
return NULL;
}
int sizeOfBlock=*(int*)ptr+13;
void* copy = malloc(sizeOfBlock);
if (!copy) {
return NULL;
}
for(int i=0;i<sizeOfBlock;i++){
*(copy+i)=*(ptr+i);
}
return copy;
}
but I get: invalid use of void expression
You cannot dereference, perform pointer arithmetic, indexing a void pointer because it has no base type or object size. You must therefore cast the void pointer to the a pointer to the type of the data units you are copying so that the compiler will know the size of the data to copy.
All that said, you'd be better off using:
memcpy( copy, prt, sizeOfBlock ) ;
This design (storing block size inside of a block without any struct) seems dangerous to me, but I still know the answer.
*(copy+i)=*(ptr+i);
Here you get the error, because you can't dereference a void pointer. You need to cast it to pointer to something before. Like this:
((char *)copy)[i] = ((char *)ptr)[i];
You should use the memcpy function:
memcpy(copy, ptr, sizeOfBlock);
Depending on the compiler settings (you may be compiling as C++ and not as C), you may need to cast the pointers to a char pointer:
memcpy((char *) copy, (const char *) ptr, sizeOfBlock);
Note: The parameter of the function should be const char *ptr, to make sure you don't change the contents of ptr by mistake.

what this (int**)&p; mean in the statement?

This code is practice code for pointers. But I am not understanding the (int**)&p; means in this code.
void fun(void *p);
int i;
int main()
{
void *vptr;
vptr = &i;
fun(vptr);
return 0;
}
void fun(void *p)
{
int **q;
q = (int**)&p;
printf("%d\n", **q);
}
Please elaborate how it is evaluated.
It's a type cast, that interprets the value of &p, which has type void **, as instead having type int ** which is the type of the variable the value is stored in.
The cast is necessary, since void ** is not the same as void * and does not automatically convert to/from other (data) pointer types. This can be confusing.
&p being of type void**, is being casted to type of int** which is to be assigned to q.
SIDE-NOTE : "Any pointer can be assigned to a pointer to void. It can then be cast back to its original
pointer type. When this happens the value will be equal to the original pointer value."
Be careful when using pointers to void. If you cast an arbitrary
pointer to a pointer to void, there is nothing preventing you from
casting it to a different pointer type.

What is the use of void** as an argument in a function?

I have to implement a wrapper for malloc called mymalloc with the following signature:
void mymalloc(int size, void ** ptr)
Is the void** needed so that no type casting will be needed in the main program and the ownership of the correct pointer (without type cast) remains in main().
void mymalloc(int size, void ** ptr)
{
*ptr = malloc(size) ;
}
main()
{
int *x;
mymalloc(4,&x); // do we need to type-cast it again?
// How does the pointer mechanism work here?
}
Now, will the pointer being passed need to be type-cast again, or will it get type-cast implicitly?
I do not understand how this works.
malloc returns a void*. For your function, the user is expected to create their own, local void* variable first, and give you a pointer to it; your function is then expected to populate that variable. Hence you have an extra pointer in the signature, a dereference in your function, and an address-of operator in the client code.
The archetypal pattern is this:
void do_work_and_populate(T * result)
{
*result = the_fruits_of_my_labour;
}
int main()
{
T data; // uninitialized!
do_work_and_populate(&data); // pass address of destination
// now "data" is ready
}
For your usage example, substitute T = void *, and the fruits of your labour are the results of malloc (plus checking).
However, note that an int* isn't the same as a void*, so you cannot just pass the address of x off as the address of a void pointer. Instead, you need:
void * p;
my_malloc(&p);
int * x = p; // conversion is OK
Contrary to void *, the type void ** is not a generic pointer type so you need to cast before the assignment if the type is different.
void ** ptr
Here, "ptr" is a pointer to a pointer, and can be treated as a pointer to an array of pointers. Since your result is stored there (nothing returned from mymalloc), you need to clarify what you wish to allocate into "ptr". The argument "size" is not a sufficient description.

Resources