In C, you should not cast the result of malloc
(or related functions like calloc
/realloc
). Below are detailed examples and explanations to clarify why casting is unnecessary and potentially harmful.
1. Basic Usage (No Cast Needed)
Good Practice:
#include <stdlib.h>
int main() {
// Allocate memory for 10 integers
int *arr = malloc(10 * sizeof(int));
// Allocate memory for a struct
struct Point { int x; int y; };
struct Point *p = malloc(sizeof(struct Point));
free(arr);
free(p);
return 0;
}
malloc
returns avoid*
, which implicitly converts to any pointer type in C.- No cast is required, and the code remains clean.
Bad Practice (Redundant Cast):
int *arr = (int*)malloc(10 * sizeof(int)); // Unnecessary cast
- Adds visual noise and provides no benefit.
2. Avoiding Silent Bugs
Example: Missing <stdlib.h>
If <stdlib.h>
is not included, the compiler assumes malloc
returns an int
.
- Without Cast: Compiler warns about implicit declaration.
// Missing #include <stdlib.h>
int *arr = malloc(10 * sizeof(int)); // Warning: "implicit declaration of 'malloc'"
- With Cast: Compiler warning is suppressed! ❌
int *arr = (int*)malloc(10 * sizeof(int)); // No warning (but undefined behavior)
Casting hides this critical error, risking crashes on systems where int
and pointers differ in size.
3. Maintenance-Friendly Code
Example: Changing the Pointer Type
If you later change the type of arr
, the cast must also be updated:
// Original code (with cast)
float *arr = (float*)malloc(10 * sizeof(float));
// After changing to "double*"
double *arr = (float*)malloc(10 * sizeof(float)); // Wrong cast! Undetected error.
Without a cast, you only need to update the left-hand side:
// Original code (no cast)
float *arr = malloc(10 * sizeof(float));
// After changing to "double*"
double *arr = malloc(10 * sizeof(double)); // Safe and correct.
4. Best Practice for sizeof
Use sizeof
with the dereferenced pointer instead of the type. This avoids errors if the type changes:
int *arr = malloc(10 * sizeof(*arr)); // sizeof(*arr) = sizeof(int)
If arr
’s type changes to double*
, the code remains correct:
double *arr = malloc(10 * sizeof(*arr)); // sizeof(*arr) = sizeof(double)
5. Edge Cases
Casting for C++ Compatibility
In C++, you must cast malloc
because void*
cannot implicitly convert to other pointer types:
// C++ requires a cast
int *arr = static_cast<int*>(malloc(10 * sizeof(int)));
However, in pure C, this is unnecessary and discouraged.
6. Common Mistakes
Incorrect Allocation Size
Casting does not prevent logical errors like this:
// Allocates space for 10 pointers, not 10 integers! ❌
int *arr = (int*)malloc(10 * sizeof(int*)); // Wrong: sizeof(int*) != sizeof(int)
No cast would make this mistake more obvious:
int *arr = malloc(10 * sizeof(int*)); // Still wrong, but easier to spot
Summary: Why No Cast?
- Redundant in C:
void*
auto-converts to any pointer type. - Safety: Avoids hiding compiler warnings (e.g., missing headers).
- Maintainability: Reduces code changes during refactoring.
- Clarity: Keeps code concise and readable.
Key Takeaways
- Never cast
malloc
in C. - Always use
sizeof
with the dereferenced pointer (e.g.,sizeof(*ptr)
). - Include
<stdlib.h>
to ensuremalloc
is properly declared.
By following these rules, your code becomes safer, cleaner, and easier to maintain.