Pointer casting is a common operation in C that allows for the use of generic interfaces, for example, working with memory through void* or implementing universal data structures. However, type casting of pointers comes with certain risks and follows strict standards.
void* in C holds an address but does not know the type of the content it points to. Any other pointer (such as int*, char*, struct mytype*) can be explicitly (or implicitly) cast to void* and back without loss of information (as long as no "narrowing" occurs).void*), you must be sure that a compatible type's value really exists at that address.void process(void *data) { int *arr = (int*)data; // use arr as an array of int } int main() { double x = 10; process(&x); // DANGEROUS: casting double* to int*, UB }
"Can any pointer be safely cast to void* and back without loss?"
Many answer "yes"—after all, the C standard guarantees transforming any object pointer to void* and back without loss. But it's important to remember: if you cast a non-object pointer (such as a pointer to function) to void* or mix different architectures (pointer sizes differ for functions and data), you will encounter undefined behavior.
void foo() {} void *p = (void*)foo; // UB! function pointer cannot be cast this way
Story
In a project with a cross-platform data processing subsystem, a handler was used that cast a pointer to a structure to
void*, then back to the original type. When transitioning to an architecture whereint*anddouble*had different alignments, an attempt to castvoid*to the incorrect type led to a "bus error" (crash).
Story
In an embedded project, a programmer implemented a ring buffer with a generic interface on
void*, but forgot about strict alignment requirements (allocated memory for achararray, passed it asint*). On some platforms, the data became "incomprehensible to the hardware"—reading errors and unstable operation occurred.
Story
In a dynamic collection, addresses were stored as
void*, but it was forgotten that a function pointer cannot be cast tovoid*. Trying to store and pass an event handler (callback) through such a field led to crashes on certain platforms, making it very difficult to catch the error.