Kris_Holder
Kris_Holder

Reputation: 91

void * as a function parameter

I've problem using void *. How should I do to use this clean_buffer function for int and float arrays.

void clean_buffer( void *ptr, int n)
{
    for( int i = 0; i < n; i++)
        ptr[i]=0;
}
int main(void)
{
   float  *pf;
   int    *pi;

   pf = (float *) malloc(10*sizeof(float));
   pi = (int *)malloc(10*sizeof(int));


   clean_buffer( (float *)pf, 10);
   clean_buffer( (int *)pi, 10);

    return 0;
}

Upvotes: 1

Views: 400

Answers (6)

chux
chux

Reputation: 153338

I've problem using void *. How should I do to use this clean_buffer function for int and float arrays (?)

Others have mentioned useful things like the need to sizeof to find the size, cast not needed and alternatives to use calloc() for a zero initialized memory allocation.


To add:

sizeof *object_pointer

Use sizeof *object_pointer to find the size. It is less error prone, easier to review and maintain than coding in the type.

// clean_buffer( (float *)pf, 10);
// clean_buffer( (int *)pi, 10);

// cast not needed
clean_buffer(pf, sizeof *pf * 10);  // No need to mention type!
clean_buffer(pi, sizeof *pi * 10);

volatile

Scrubbing memory after its final use is prone to being optimized out and then a good reason to not use memset() when memory security is of concern. Instead use volatile to prevent clean_buffer() from itself being optimized out.

void clean_buffer(void *ptr, size_t n) {
  volatile unsigned char *vuc = ptr;
  for(size_t i = 0; i < n; i++)
    vuc[i]=0;
  }
}

Upvotes: 1

Gerhardh
Gerhardh

Reputation: 12404

Type void has no size. Therefore you cannot use void * to clear an array. You can not dereference that type for the same reason.

You must cast to a pointer with specific type:

void clean_buffer(void *ptr, size_t n)
{
    unsigned char *my_ptr = ptr;
    for (int i = 0; i < n; i++)
        my_ptr[i]=0;
}

You need to take care that the size passed to your function cannot be the number or arrays because the compiler cannot do pointer arithmetics with void* pointers. And for sizes you should use size_t

Instead you have to pass the size of the array in bytes:

int main(void)
{
   float  *pf;
   int    *pi;

   pf = malloc(10*sizeof(float));
   pi = malloc(10*sizeof(int));

   clean_buffer( pf, 10*sizeof(float));
   clean_buffer( pi, 10*sizeof(int));

   return 0;
}

Or you need to pass any other information that can be used to determine type and/or size of the data.

Also: Casting the return value of malloc is not needed in C. Casting the parameters of clean_buffer to a type that the variable already has, is useless. The pointer type is converted to void * anyway as this is what the function expects.

Note: Other answers and comments mention that you could simply pass the pointer to memset or use calloc etc. This might be true for this very specific case but if you want to do anything else than simply zeroing the memory, the same aspects regarding void * pointers apply as I have shown here. And in those cases memset or calloc are of no help.

Upvotes: 2

Jay
Jay

Reputation: 24895

malloc itself returns a void pointer as it doesn't really know for which type you are allocating memory. So, you need to use the same size which you pass to malloc for clearing the buffer also.

You can use memset and pass the size of the entire buffer to clear it without having to worry about it's type.

void clean_buffer( void *ptr, size_t n)
{
    memset(ptr, 0, n)
}
int main(void)
{
   float  *pf;
   int    *pi;

   pf = (float *) malloc(10*sizeof(float));
   pi = (int *)malloc(10*sizeof(int));


   clean_buffer(pf, 10*sizeof(float));
   clean_buffer(pi, 10*sizeof(int));

    return 0;
}

Additionally, as others have suggested, you can use calloc if it suits you.

Upvotes: 0

Immo Hellwig
Immo Hellwig

Reputation: 1

void clean_buffer( void *ptr, int n)

This function demands a void * as a parameter.

clean_buffer( (float *)pf, 10);

Here you are casting to a float pointer. So this a different type as demanded

Also void has no size, so you cant really use [] on ptr

Upvotes: 0

bruno
bruno

Reputation: 32586

void is a non value you cannot use *((void*) x) = v; and to use a cast to use a pointer to an other type is dangerous because the size may not be the same

But, in your case you set to 0, so you can use memset or replace the malloc my calloc and it is useless to have clean_buffer :

int main(void)
{
   float  *pf;
   int    *pi;

   pf = calloc(10, sizeof(float));
   pi = calloc(10, sizeof(int));

   return 0;
}

Upvotes: 2

Scott Hunter
Scott Hunter

Reputation: 49803

You cast ptr to the appropriate type so it can dereferenced to clear what it points to; something you know points to a type that you want to clear i items of.

Upvotes: 0

Related Questions