What is the purpose of void in C?

28

I have questions about using void in functions.

1 ° Example:

int somaV(int valor_1, int valor_2)
{
    return valor_1 + valor_2;
}

I know that this function will return an integer which is the sum of the two parameters in the function valor_1 and valor_2 .

2nd Example:

void* soma(int valor_1, int valor_2)
{
    return (int) valor_1 + valor_2;
}

I saw in a program that contained a similar implementation like the second example above that I used to illustrate the situation I witnessed using void . I have tried the soma() function and it returns the sum of the two parameters even though the void is specified as a return or empty.

This made me confused about using void , I thought it was just to say that a function will not have any return or will not receive any parameters like this example soma(void) .

After all, what is the purpose of this command in C? Can the% use of specified% as a pointer return values even though void* ?

    
asked by anonymous 09.11.2015 / 15:54

3 answers

28

Return void means no return. Already a type void * means a generic pointer, a pointer of an unknown or unspecified type, a pointer to anything, any memory address.

They appear a lot in the C language, although the programmer does not always notice them. For example, the malloc function returns a pointer of type void * :

int *meu_numero = (int *) malloc(sizeof(int));

Here, the return of malloc is of type void * . The cast for int * is required for you to tell the compiler type checker to consider that the value returned (which the compiler will know to be void * ) should be considered to be a int * . In this case, you get a pointer of unknown type and then tell the compiler which one is the type. One proof of this is that this same code can be written in another equivalent way, denouncing void * :

void *algum_ponteiro = malloc(sizeof(int));
int *meu_numero = (int *) algum_ponteiro;

The void * can also appear as a parameter, as in the free function. The free function can receive any type of pointer, no matter what the exact type of object is pointed to. Because of this the type of your parameter is also void * .

Other functions also use or produce pointers of type void * , especially those that work with things in memory without wanting to know exactly what these things are, but only that it is some region in memory. Example of functions like this are fread , fwrite , memset , among many others.

    
09.11.2015 / 16:16
16

void * strictly means a pointer to nothing. But it is best interpreted as pointer to anything. That is, this is a way to generalize a type, to stop specifying the type.

When you use it, it means that you can work with any type of data there. It simply points to a memory address and it is the problem of the programmer who will receive it to know how to handle properly and probably make a cast for the desired type, in a way compatible with what has there. Obviously tragedies can happen if you try to access inappropriately.

Care is taken when using it because it loses one of the advantages of C. It is a way of creating dynamism in a statically typed language. It's also a form of polymorphism.

Note that you are returning a pointer.

int x;
float y;
char * z;

void * var;
var = &x;
var = &y;
var = &z; //ou dependo da intenção: var = z;
    
09.11.2015 / 16:05
11

void* pointers precede C ++ and templates as a mechanism for dealing with "generic" types in C. To be more specific void represents the absence of type, which can be understood as the presence of any kind. As you have already discovered, you can assign int , char or any other type to void* .

With void* functions that do not need to know the type details can do their job. The programmer, who knows the type, can do the necessary casts when needed ... See what absence of types basically places the typing responsibility on the programmer's back.

Why is this useful?

One of the best examples of using void* is the qsort function whose signature is:

void qsort (void* base, size_t num, size_t size,
            int (*compar)(const void*,const void*));

With qsort we can sort an array base of any type. You just need to define a function of type int compar (const void* p1, const void* p2) able to compare the types of array base .

Example:

int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}

//...
int values[] = { 40, 10, 100, 90, 20, 25 };
qsort (values, 6, sizeof(int), compare);

You could have a method for comparing char* , or maybe for a specific type of struct or something else. Thanks to void pointers the qsort function is "generic".

But what about functions that return void pointers *?

The idea is the same. Generic APIs can work with multiple return types. A good example is the int pthread_setspecific(pthread_key_t key, const void *value) and void *pthread_getspecific(pthread_key_t key) function pair of% pthreads.h . You can store and retrieve any type of value thanks to the use of void* .

Other good examples are the ** alloc * functions as well mentioned in the previous answers. In c you do not and should not cast from the result of malloc (this has changed in C ++):

// C
int *arr= malloc(sizeof(int)*length);
// C++ escrito para ser compatível com C
int *arr= (int *)malloc(sizeof(int)*length);
// C++ "de verdade"
int *arr= new int[length];
// C++11 - Melhor ainda, esqueça o delete
std::unique_ptr<int[]> arr(new int[10]);
09.11.2015 / 16:44