Reputation: 476
I have a function which returns an array Data
. The type of the array is either int
or float
. I would like to use void
pointers. If outputType
is 0 the Data
would a pointer to an integer array, if not it will point to a float array.
Is it possible to perform this in C?
void getData(void *Data , uint8_t outputType)
{
...
int16_t acc[3]={0,0,0};
...
acc[0] = (int16_t) ((data[1]*256+data[0]));
acc[1] = (int16_t) ((data[3]*256+data[2]));
acc[2] = (int16_t) ((data[5]*256+data[4]));
Data = acc;
}
In the main code:
int16_t output[3];
getData(output, 0);
Upvotes: 1
Views: 1928
Reputation: 16243
You can do something like this :
void getData(void *Data , uint8_t outputType) {
if (outputType == 0) {
int16_t* data = Data;
/* fill int16_t data here - eg. : */
data[0] = 42;
}
else {
float* data = Data;
/* fill float data here - eg. : */
data[0] = 42.0f;
}
}
All assuming you call it either as :
int16_t output[3];
getData(output, 0);
or :
float output[3];
getData(output, 1);
Take special care not to exceed the bounds of the array.
Explanation
Any pointer to an object type can be converted to a void*
and back again to the original type, and the resulting pointer will compare equal to the original pointer.
This can be used (as in this case) to implement generic functions that can work on any pointer type (ref. eg. What does void* mean and how to use it?).
There is a caveat though : a void*
can't be dereferenced (nor can pointer arithmetic be performed on it), so it has to be converted back to the original pointer type before dereferencing. The outputType
parameter says exactly what that original pointer type was, so the function can perform the proper conversion.
After that, the function can work on the converted pointer as if it were the original pointer. If the original pointer points to an array, then the converted pointer can also be used to access all items of that array.
Upvotes: 7
Reputation: 114270
It is quite possible to do what you want, but not quite the way you are trying to do it. If you want to pre-allocate the buffer as you are doing, that's fine, and you only need to pass in the pointer itself. Then your problems begin.
First of all, three int16_t
are not going to be enough to hold the same number of float
elements (which are usually 4 bytes each). You need to make sure the buffer you pass in is big enough to hold the output.
Secondly, the assignment Data = acc;
just copies the value of the pointer, not the data that it contains. To do that, you would have to use memcpy(Data, acc, 3 * sizeof(uint16_t));
, memmove(Data, acc, 3 * sizeof(uint16_t));
, or something similar. More simply, you could stash the values in the Data
buffer directly instead of messing with acc
in the first place.
Upvotes: 2