1

Why are void pointers necessary, as long as one could cast any pointer type to any pointer type, i.e.:

char b = 5; 
int*a = (int*)&b;//both upcasting

or

int b = 10;
char*a = (char*)b;//and downcasting are allowed

?

Also, why there is no need for cast when using malloc/calloc/realloc ?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
pauk
  • 350
  • 4
  • 15
  • [Do I cast the result of malloc?](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – kaylum Feb 04 '21 at 02:42
  • "why there is no need for cast when using malloc/calloc/realloc" covered well in [Do I cast the result of malloc?](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – chux - Reinstate Monica Feb 04 '21 at 02:54
  • @pauk "could cast any pointer type to any pointer type" --> curious, who or what text suggested that? – chux - Reinstate Monica Feb 04 '21 at 03:01
  • @pauk I took time to address your [comment](https://stackoverflow.com/questions/66038594/what-is-the-purpose-of-void-pointers/66038686?noredirect=1#comment116764100_66038686). What thoughts on my [comment](https://stackoverflow.com/questions/66038594/what-is-the-purpose-of-void-pointers/66038686?noredirect=1#comment116759718_66038594)? – chux - Reinstate Monica Feb 04 '21 at 13:12

3 Answers3

4

one could cast any pointer type to any pointer type

Not quite. void * is defined to convert any object pointer1 to void * and back again with an equivalent value. It does not need any cast.

In less common architectures, the size and range of some other pointers may be smaller than void *. Casting between other pointers type may lose necessary information.

void * provides a universal object pointer type.

void *p = any_object_pointer; // No casts required
any_object_pointer = p;       // No casts required

char * could substitute for void *, except conversion to and from other object pointers requires casts.


OP's char b = 5; int*a = (int*)&b; risks undefined behavior as the alignment needs of int * may exceed char *.


1 Function pointers may be wider than void*. void * and other pointers are object pointers. C lacks a truly universal pointer type.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Important to note that changing the pointer type, does not change the type of object pointed to, hence, it's not generally safe to cast between any arbitrary types of pointers. – jwdonahue Feb 04 '21 at 02:58
  • Indeed, I see that C needs a universal type pointer that should not be cast explicitly. Nevertheless, I cannot see why it is risky to cast to a particular type of pointer, as long as the pointer type matters only in terms of pointer arithmetic, because pointers point to a memory location regardless of their type. – pauk Feb 04 '21 at 07:59
  • Also, maybe I should open another topic, but I cannot see the purpose of the cast itself, as long as the pointer type matters only when it comes to pointer arithmetic, thus, passing a char* for example, to an int* cannot spoil the contents of the memory. – pauk Feb 04 '21 at 08:02
  • @pauk "as long as the pointer type matters only in terms of pointer arithmetic," is not true. 1) "passing a char* for example, to an int*" creates problems. Example: when an `int *` only works with even address and `char *` can handle eve/odd ones. 2) types allows for optimizations - research anti-aliasing as the compiler "knows" manipulating an object via `double *` does not change something via an `int *`. Also research `restrict` 3) Casting defeats types checking. Such weak type checking belongs to C predecessors - which we do not hear about for a good reason - too easy to code wrong. – chux - Reinstate Monica Feb 04 '21 at 13:00
  • I understand better. Thanks – pauk Feb 04 '21 at 13:26
1

void pointers are really useful to create a generic API. You might think of qsort function which can be used to sort arrays of any types. void pointers can be used if the API does not know the concrete type of the pointer.

void qsort(
   void *base,
   size_t number,
   size_t width,
   int (__cdecl *compare )(const void *, const void *)
);

Regarding allocation functions, it's the same thing. The C runtime does not know the type of the effective object. But this is not a problem as user can use generic pointer void.

So void pointers are considered as generic pointers, very useful for polymorphism, that's why the C language makes casting to void optional.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Robert
  • 2,711
  • 7
  • 15
0

"Why are void pointers necessary, as long as one could cast any pointer type".

The alloc function would then have to use common denominator such as char. But then it would be confusing to have to cast to whatever we really need. "void" just means "a bunch of bytes".

Tarik
  • 10,810
  • 2
  • 26
  • 40