可以使用结构的大小来创建标识符吗?

时间:2014-08-20 05:05:58

标签: c macros c-preprocessor

假设我有一个我想根据类型的大小调用的函数。

有没有办法可以使用宏来完成?

static int array_find_index_4_impl(void *array, const unsigned int arr_len, const void *var)
{
    const int32_t *arr_step = arr;
    unsigned int i;
    for (i = 0; i < arr_len; i++, arr_step++) {
        if (*arr_step == *(int32_t *)var) {
            return (int)i;
        }
    }
    return -1;
}

static int array_find_index_2_impl(void *array, const unsigned int arr_len, const void *var)
{
    const int16_t *arr_step = arr;
    unsigned int i;
    for (i = 0; i < arr_len; i++, arr_step++) {
        if (*arr_step == *(int16_t *)var) {
            return (int)i;
        }
    }
    return -1;
}
/* etc... for other sizes too */

#define array_find_index(array, array_len, var) \
    array_find_index_##SOME_MAGIC_SIZEOF(*array)##_impl(array, array_len, var)

可能的解决方案......

我知道C11的_Generic可用于检查特定类型,但我有兴趣忽略确切类型并仅根据大小找到合适的函数。


另一种选择可能是存储函数的查找表,例如:

#define array_find_index(array, var) \
    array_find_index_fn_table[sizeof(*array)](array, var)

哪个可行,但如果可能的话,更愿意直接构建标识符。


当然可以将sizeof传递给函数并使用memcmp,但我很想知道是否从结构大小创建标识符

3 个答案:

答案 0 :(得分:2)

另一种可能的解决方案是生成一些具有相关类型大小的X-macro头文件,即生成类似

的文件
#define MY_SIZEOF_int 4

等等....使用一些包含

的简单C生成文件
#define WANT_SIZE(Typ)  {              \
   printf("#define MY_SIZEOF_%s %d\n", \
          #Typ, (int) sizeof(Typ)); };

并在某处

WANT_SIZE(int)
WANT_SIZE(my_struct_t)

并在构建过程中运行专用生成器...

之前假设一些typedef struct my_struct_st my_struct_t(因为这仅适用于简单命名的类型)。

当然,这需要复杂化构建过程(例如,在Makefile中添加几个规则和目标...)

另一个解决方案可能是使用GCC ...)__builtin_type_compatible_p或甚至自定义它(通过添加您的特定编译指示或内置函数){{ 3}}。

答案 1 :(得分:0)

  

我有一个我想根据类型的大小调用的函数。   有没有办法可以使用宏来完成?

仅使用宏,不能这样做。宏由预处理器消耗,在这个阶段没有识别标识符的类型,更不用说它的大小了。 换句话说,预处理器只是没有做你想做的事所需的信息。

然而,根据类型大小调用函数的原始问题的解决方案当然可能涉及一些预处理,就像你提出的那样。

答案 2 :(得分:-1)

#include <stdio.h>
#include <string.h>

static int array_find_index(const void *array, const void *value, size_t numOfMember, size_t element_size){//option add compare function
    size_t i;
    const char *p = (const char *)array;
    for(i = 0; i < numOfMember; ++i, p += element_size){
        if(memcmp(p, value, element_size)==0)
            return (int)i;
    }
    return -1;
}

#define ARRAY_FIND_INDEX(array, var) \
    array_find_index(array, var, sizeof(array)/sizeof(*array), sizeof(*array))

int main (void){
    int ia[] = {1,2,3,4,5};
    int ikey = 3;
    int index = ARRAY_FIND_INDEX(ia, &ikey);
    printf("%d\n", index);
    char ca[] = {'1','2','3','4','5'};
    char ckey = '5';
    index = ARRAY_FIND_INDEX(ca, &ckey);
    printf("%d\n", index);
    ckey = '0';
    index = ARRAY_FIND_INDEX(ca, &ckey);
    printf("%d\n", index);
    return 0;
}