简体   繁体   中英

Returning a void pointer as a function parameter in C

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);

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM