Out of the void

The four standard data types in C programming are char, int, float, and double. A fifth type is void, which is used to declare storage of an unknown type. My goal is to see how badly I can abuse this data type.

The void data type used primarily with pointers. For example, in the qsort() function, the compar() function is prototyped like this:

int (*compar)(const void *, const void *));

The const void * argument represents a pointer of an unknown type. When you code your own compar() function, you substitute const void * with a pointer based on the data type of whatever data the qsort() function is sorting. The void placeholder serves to represent a non-specific pointer type, but can I pervert it to be used for a standard data type on-the-fly?

In the following code, I need an integer value. I declare variable a as a void, which is wrong but will it work?

2024_04_20-Lesson-a.c

#include <stdio.h>

int main()
{
    void a;

    printf("Enter an integer: ");
    scanf("%d",a);
    printf("You entered %d\n",a);

    return 0;
}

This code won’t build. The error generated is “incomplete type.” The void type doesn’t allocate storage for anything (hence, “void”). The C language documentation says that void can be cast. So how about this modification:

2024_04_20-Lesson-b.c

#include <stdio.h>

int main()
{
    void a;

    printf("Enter an integer: ");
    scanf("%d",(int)a);
    printf("You entered %d\n",(int)a);

    return 0;
}

Above, I’ve added the (int) typecast to variable a where it’s used in the scanf() and printf() functions. The code doesn’t build, again generating an “incomplete type” error. So much for being sneaky.

The void data type cannot be used to represent a value in any way, specifically to convert a non-void type, which is what I’m trying to do in this code.

Obviously, the solution is to declare variable a as an int. With this modification, the program runs and everyone gets a cupcake. But I’m stubborn about these things.

The void type is used with pointers, as shown earlier with the compar() prototype example. So I can use the void declaration to assign a storage for an integer, then use its pointer to manipulate data. Here’s a final modification:

2024_04_20-Lesson-c.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
    void *a;

    a = malloc(sizeof(int));

    printf("Enter an integer: ");
    scanf("%d",(int)a);
    printf("You entered %d\n",(int)a);

    return 0;
}

The malloc() function allocates an integer-sized chunk of storage for variable a. This program builds, but generates three warnings regarding the (int) cast. Here’s the output:

Enter an integer: 100
Segmentation fault

At this point, the code approaches one of those challenges where beginning C programmers know that an asterisk is required — but where? Two puzzles must be solved.

The first puzzle is that the scanf() function requires the address of a value — a pointer. Variable a is a pointer. But do you typecast it? What about this: scanf("%d",a); ? If you try, which kind of makes sense, you get a type mismatch error as %d requires an integer and a is a void pointer type.

The second puzzle occurs in the printf() statement, where a is again a void pointer despite being cast an an integer. How do you properly code this value as an integer?

In next week’s Lesson I cover how to resolve these issues.

Leave a Reply