C中的动态类型转换

问题描述:

我正在尝试编写一个以缓冲区(void *),类型大小,类型名称和元素数量为参数的函数.缓冲区可能包含有限数量的基本类型(int,float,double,...)的值.在这个函数中,我希望能够增加每个值.看起来像这样:

I'm trying to write a function taking as a parameter a buffer (void *), the type size, the type name and the number of elements. The buffer may contain values of a limited number of basic types (int, float, double, ...). Within this function, I would like to be able to, let's say, increment each value. It looks like that :

void increment (void *buffer, int type_size, char *type_name, int n_elements)
{
    for (int i=0;  i<n_elements; i++)
        ((MACRO(type_name))(buffer))[i]++; // ???

    return;
}   

我的问题很简单:如何动态"投射缓冲区?如果需要,我可以添加更多的功能参数.也许可以使用宏完成某些操作,但我无法弄清楚.

My question is as simple as: how can I "dynamically" cast my buffer? I can add more function parameters if needed. Maybe something can be done using macros but I can't figure this out.

如果要处理的特定类型数量有限,则可以为每种类型编写单独的函数.如果不想为每种类型选择正确的功能,则可以使用C11的 _Generic 根据类型进行选择.作为一个基本示例:

If you are dealing in a finite number of specific types for this to work with, you could write a separate function for each type. If you don't want to have to pick the right function for each type, you can use C11's _Generic to select based on the type. As a basic example:

#include <stdio.h>
#include <stdlib.h>

void increment_int(int *, int);
void increment_long_long_int(long long int *, int);

#define increment(buffer, n_elements) _Generic((buffer), \
                int *:  increment_int, \
      long long int *:  increment_long_long_int \
      )(buffer, n_elements)

void increment_long_long_int (long long int *buffer, int n_elements)
{
    for (int i=0;  i<n_elements; i++)
    {
        buffer[i]++;
    }
    return;
}   

void increment_int (int *buffer, int n_elements)
{
    for (int i=0;  i<n_elements; i++)
    {
        buffer[i]++;
    }
    return;
}

int main(void) {
    int buff[20] = {0};
    long long int buff2[20] = {0};
    increment(buff, 20);
    increment(buff2, 20);
    printf("%d\n", buff[5]);
    printf("%lld\n", buff2[8]);
    return EXIT_SUCCESS;
}