Home > OS >  void pointer type cast with (unsigned int *) and (unsigned int **)
void pointer type cast with (unsigned int *) and (unsigned int **)

Time:06-09

unsigned int num = 101;

void * p = #

void ** pp = &p;

unsigned int *get_data_1 = NULL;
unsigned int *get_data_2 = NULL;

get_data_1 = *((unsigned int *)pp);

get_data_2 = *((unsigned int **)pp);

Here get_data_1 and get_data_2 what will be the difference?

I have type casted with (unsigned int *) and (unsigned int **).

CodePudding user response:

Both operations invoke Undefined Behavior. The value of type void* pointed by pp is accessed via a l-value expression of incompatible type unsigned int or unsigned int* respectively. This violates strict aliasing rule.

As both operations are UB thus there is no defined difference between those two operations.

The correct accessing should be by dereferencing pp first to obtain value of type void* and use implicit casting from void* to unsigned int*. Finally dereference correctly typed pointer:

unsigned int *get_data_3 = *pp;
return *get_data_3;

CodePudding user response:

TL;DR

Don't do any of this, it is dangerous and incorrect C for a number of reasons. My general advise to beginners is to never use the cast operator at all - there shouldn't be a lot of situations where you actually need to use it.


Generally, C allows wild and dangerous pointer conversions between object pointers that are not compatible, as long as there are no alignment concerns regarding the type pointed-at. (6.3.2.3/7)

However, should you first cast to a non-compatible type and then de-reference the pointer, all manner of undefined behavior might kick in. 6.7.6.1:

For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.

Also there are the whole "strict aliasing" concerns regarding "lvalue access" (6.5).

Specifically:

  • (unsigned int *)pp the pointer conversion is probably ok given that pp points at an aligned address.
  • *((unsigned int *)pp) invokes undefined behavior since a lvalue of type void* is accessed as an unsigned int and they are not compatible types.
  • unsigned int *get_data_1 = <unsigned int lvalue> is a constraint violation - invalid C. As per 6.5.16.1. C has never allowed an integer to get assigned to a pointer and vise versa, explicit casts are required.
  • (unsigned int **)pp similarly the pointer conversion in itself is "probably ok". But again unsigned int** is not compatible with void**. Notably, the special generic rules regarding void* conversions do not apply to void**.
  • *((unsigned int **)pp) accesses a void* as a unsigned int*. Again this is a strict aliasing violation, because although we may convert to/from void* to any object pointer, they need not have the same internal presentation (though in practice it's very likely). They are not compatible types as per the quoted 6.7.6.1.
  • unsigned int *get_data_2 = <unsigned int* lvalue> is ok.
  •  Tags:  
  • c
  • Related