i've searched a solution to solve the issue of controlling data type for while , and i thought that maybe my founding could add up well with the initial demand @con-f-use, even if it's no exactly the same issue.
An other way around to control the datatype could be done using an union  with predefined type. In my case, i had a defined structure in which i was originally using a void* to allow divers data type to be passed :
originally:
//[main]: 
uint32_t vtest3= 100000;
int32_t vtest2= 100000;
struct entity list[] = {
  { TYPE_INT32,     s_int32_t,  .label="tension", &vtest3},
  { TYPE_INT32,     s_int32_t,  .label="tension", &vtest3}
};
//[file.h]:
struct entity {
   enum entity_type type;
   uint32_t dimension;
   char* label;
   void* ptr_data;
    uint32_t offset;
};
enum  entity_type {
  TYPE_NONE     = 0,
  TYPE_INT8     = 1,
  TYPE_INT16    = 2,
  TYPE_INT32    = 3,
  TYPE_INT64    = 4,
  TYPE_UINT8    = 5,
  TYPE_UINT16   = 6,
  TYPE_UINT32   = 7,
  TYPE_UINT64   = 8,
  TYPE_FLOAT32  = 9
};
The issue with this method is that it  accept all  type of variable  in an uncontrolled way. There is no easy method to control the data type referenced by the void* pointer, Excepted maybe thought the use of a macro and _Generic as described before in this thread.
If the programmer decided to pass a type different from the list of type accepted ,there while be no error thrown at compile time.
. They other way around  is by replacing the void* by an union , this way the structure  while only accept specific data type defined inside the union list . If the programmer decide to pass a pointer with an type which is not already defined inside the ptr_data union{...} , it will throw an error.
//[file.h]:
enum  entity_type {
  TYPE_NONE     = 0,
  TYPE_INT8     = 1,
  TYPE_INT16    = 2,
  TYPE_INT32    = 3,
  TYPE_INT64    = 4,
  TYPE_UINT8    = 5,
  TYPE_UINT16   = 6,
  TYPE_UINT32   = 7,
  TYPE_UINT64   = 8,
  TYPE_FLOAT32  = 9
};
struct entity {
  enum entity_type type;
  uint32_t dimension;
  char* label;
  union {
    uint8_t *uint8;
    uint16_t *uint16;
    uint32_t *uint32;
    uint32_t *uint;
    int16_t *int16;
    int32_t *int32;
    int64_t *int64;
    float *f;
  } ptr_data;
  uint32_t offset;
};
[main:]
uint32_t vtest3= 100000;
int32_t vtest2= 100000;
struct entity list[] = {
{ TYPE_INT32,   s_int32_t,  .label="a", .ptr_data = {.uint16=&vtest1}
},
{ TYPE_INT32,   s_int32_t,  .label="b", .ptr_data = {.int32=&vtest2}
};
This method make use of the union to control implicitly the data type of the variable inserted  by the programmer in the structure. If not correct the compiler while throw an error at compile time.
Obviously this  code example is far from perfect and cannot be used directly but i tried to explain in a way as clear as possible the logic and the  the idea that i proposed  ;)