C Programming – Why ‘void’ Doesn’t Mean Void

cpointers

In strongly-typed languages like Java and C#, void (or Void) as a return type for a method seem to mean:

This method doesn't return anything. Nothing. No return. You will not receive anything from this method.

What's really strange is that in C, void as a return type or even as a method parameter type means:

It could really be anything. You'd have to read the source code to find out. Good luck. If it's a pointer, you should really know what you're doing.

Consider the following examples in C:

void describe(void *thing)
{
    Object *obj = thing;
    printf("%s.\n", obj->description);
}

void *move(void *location, Direction direction)
{
    void *next = NULL;

    // logic!

    return next;
}

Obviously, the second method returns a pointer, which by definition could be anything.

Since C is older than Java and C#, why did these languages adopt void as meaning "nothing" while C used it as "nothing or anything (when a pointer)"?

Best Answer

The keyword void (not a pointer) means "nothing" in those languages. This is consistent.

As you noted, void* means "pointer to anything" in languages that support raw pointers (C and C++). This is an unfortunate decision because as you mentioned, it does make void mean two different things.

I have not been able to find the historical reason behind reusing void to mean "nothing" and "anything" in different contexts, however C does this in several other places. For example, static has different purposes in different contexts. There is obviously precedent in the C language for reusing keywords this way, regardless of what one may think of the practice.

Java and C# are different enough to make a clean break to correct some of these issues. Java and "safe" C# also do not allow raw pointers and do not need easy C compatibility (Unsafe C# does allow pointers but the vast majority of C# code does not fall into this category). This allows them to change things up a bit without worrying about backwards compatibility. One way of doing this is introducing a class Object at the root of the hierarchy from which all classes inherit, so an Object reference serves the same function of void* without the nastiness of type issues and raw memory management.