Function to determine data size
This is not really an electronics or embedded systems question.

If you use C++, you can make write multiple functions under one name, thanks to overloading:

#include &lt;inttypes.h&gt;

void store_data(void *addr, uint8_t data);
void store_data(void *addr, uint16_t data);
void store_data(void *addr, uint32_t data);
void store_data(void *addr, uint64_t data);


Each overload knows how large the data is from the type of its argument.

In C, you could have a macro:

void store_data_sz(void *addr, size_t size, void *pdata);

/* data argument of macro must be an lvalue */
#define store_data(addr, data) store_data_sz(addr, sizeof (data), &amp;(data))


There is also something to be said for just having separate functions for common sizes, and then a general one for variable length:

void store_8(void *addr, int data);
void store_16(void *addr, int data);
void store_32(void *addr, unsigned long data);
void store_buf(void *addr, void *buf, size_t size);


We can have a macro interface to this, again. Here we have some system dependencies, like the assumption that if something is of size 1, it an 8 bit unit, and so on:

#define store_data(addr, data) do {                 \
  switch (sizeof(data)) {                           \
  case 1: store_8(addr, data); break;               \
  case 2: store_16(addr, data); break;              \
  case 4: store_32(addr, data); break;              \
  case 8: store_64(addr, data); break;              \
  default: store_buf(addr, &amp;(data), sizeof (data)); \
  }                                                 \
} while (0)


Since sizeof(data) is a constant expression (the exception to this being C99 variable-length arrays), we know at compile time that only one of the switch cases is reachable; any decent compiler will throw away the impossible cases.  Check the compiled code disassemble to be sure.