I was reading FFMPEG source code on extracting audio and I found these macros. What do these macros do?
#define REINTERPRET_CAST(type, variable) C_CAST(type, variable)
#define STATIC_CAST(type, variable) C_CAST(type, variable)
#define C_CAST(type, variable) ((type)variable)
//used like this
int value = 0;
int sampleIndex = 0;
uint8_t* buffer = calloc(50, sizeof(uint8_t));
value = REINTERPRET_CAST(uint8_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int16_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int32_t*, buffer)[sampleIndex];
value = REINTERPRET_CAST(int64_t*, buffer)[sampleIndex];
int ret = STATIC_CAST(float, *REINTERPRET_CAST(double*, &value));
//used like this
Used like in this code they do nothing meaningful - convert pointer to int and assign to int vartable (abstracting from the wrong syntax)
If they are used like this:
uint64_t value = *REINTERPRET_CAST(int64_t*, buffer + sampleIndex);
BTW the macro is wrong as well
#define C_CAST(type, variable) ((type)(variable))
Then it is called pointer punning and it invokes Undefined Behaviour violating strict aliasing rules.
It should be done this way:
#define pune(var, X) _Generic((var), \
uint16_t *: pune16, \
uint32_t *: pune32, \
uint64_t*: pune64 \
)(var, X)
uint16_t pune16(uint16_t *val, const void *ptr)
{
memcpy(val, ptr, sizeof(*val));
return *val;
}
uint32_t pune32(uint32_t *val, const void *ptr)
{
memcpy(val, ptr, sizeof(*val));
return *val;
}
uint64_t pune64(uint64_t *val, const void *ptr)
{
memcpy(val, ptr, sizeof(*val));
return *val;
}
example usage:
void foo(void *v)
{
uint32_t x;
x = pune(&x, v);
printf("%"PRIu32"\n,", x);
}