Why cast free's return value to void?

I am reading a book (Programming with POSIX Threads by Butenhof, 1997) that uses C, and I came across the following line:

(void)free(data);

Here, data is just a pointer to an allocated struct,

data = malloc(sizeof(my_struct_t));

Why is the result of free being cast to void?

From my understanding of C, this doesn't seem to make sense for two reasons:

  • The free function already returns void
  • The code is not using the return value (it's not even being assigned to a variable)

The book was written in 1997. Is this some sort of legacy thing?

The author mentions that the examples were run on Digital Unix 4.0d, but I still can't imagine a reason to ever cast the result of a function if you're not going to use that result.

7396 次浏览

This cast is not needed. It probably wouldn't have been at the time as C had been standardized in the form of C89.

If it had been, it would've been due to implicit declaration. This usually meant that the person writing the code forgot to #include <stdlib.h> and a static analyzer was being used. This is not the best workaround and a much better idea would've been to just #include <stdlib.h> instead. Here's some wording from C89 about implicit declaration:

If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration

extern int identifier();

appeared.

But that's odd because they're not casting the result of malloc either, and malloc and free are in the same header file.

It's also possible that this is just a mistake or some way to tell the reader that free returns no result.

If we are talking about the standard free function then its prototype is

void free(void *ptr);

Therefore the cast is completely useless.
Now some speculation.

The author might have forgotten to include the stdlib.h header declaring this prototype, so the compiler is assuming the return type of it as int. Now during static analysis of this code the compiler was warning about the unused return value of what it thinks to be a non-void function. Such a warnings are usually silenced by adding the cast to void.

It would be a legacy thing!

Before there was a C standard, the free() function would have been (implicitly) of type int — because there was not yet reliably a type void for it to return. There was no value returned.

When the code was first modified to work with standard C compilers, it probably didn't include <stdlib.h> (because it didn't exist before the standard). Old code would write extern char *malloc(); (maybe without the extern) for the allocation functions (similarly for calloc() and realloc()), and didn't need to declare free(). And the code would then cast the return value to the correct type — because that was necessary on at least some systems (including the one I learned C on).

Sometime later, the (void) cast was added to tell the compiler (or, more likely, lint) that "the return value from free() is deliberately ignored" to avoid a complaint. But it would have been better to add <stdlib.h> and let its declaration extern void free(void *vp); tell lint or the compiler that there was no value to ignore.

JFTR: Back in the mid-'80s, the ICL Perq was originally on a word-oriented architecture and the char * address for a memory location was a very different number from the 'anything_else pointer' to the same location. It was crucial to declare char *malloc() somehow; it was crucial to cast the result from it to any other pointer type. The cast actually changed the number used by the CPU. (There was also much rejoicing when the main memory on our systems was upgraded from 1 MiB to 2 MiB — since the kernel used about 3/4 MiB, it meant that user programs could use 1 1/4 MiB before paging etc.)