泛型函数,用于从结构数组中提取特定结构数据成员的数组

时间:2014-04-17 18:09:22

标签: c function macros struct

如果我有结构,请说

struct mystuff {
    int a;
    int b;
    int c;
}

然后我有一组结构,

struct mystuff array[] = {...};

现在说我想将struct data成员a提取到自己的数组中

int* get_mystuff_a(struct mystuff *array, int n)
{
    int i;
    int *a_array;

    a_array = malloc(n*sizeof(int));

    for(i=0;i<n;i++) {
        a_array[i] = array[i].a;
    }
    return a;
}

现在如果我想为b做同样的事情,我必须编写另一个函数,但除了

之外它几乎是相同的
b_array[i] = array[i].b;

有没有办法可以编写一个通用函数并指定我想要提取的数据成员作为参数?

我认为宏功能可能有用,但我失去了你实际写它的方式

如果你还可以指定数据类型,那就更好了,例如:数据成员的int,float,double等 - 使其更加通用

2 个答案:

答案 0 :(得分:2)

将它写成宏很容易,而不是总是一个好主意。

在这种情况下,我认为最好编写一个构建函数的宏,而不是尝试直接内联工作:

  1. 使用非通用代码。
  2. 在每一行的末尾添加\,因为宏只是一行。
  3. 在开头添加#define NAME(...) \
  4. 在需要的地方替换宏参数。
  5. 如果需要,请不要忘记额外的括号。
  6. 结果将如下:

    #define GET_MYSTUFF(TYPE, FIELD) \
    TYPE* get_mystuff_##FIELD(struct mystuff *array, int n) \
    { \
        int i; \
        TYPE *res_array; \
        res_array = malloc(n*sizeof(TYPE)); \
        for(i=0;i<n;i++) { \
            res_array[i] = array[i].FIELD; \
        } \
        return res_array; \
    }
    

    现在您使用以下命令创建所有功能:

    GET_MYSTUFF(int, a)
    GET_MYSTUFF(int, b)
    GET_MYSTUFF(int, c)
    

    您甚至可以将输入数组类型添加为宏的另一个参数,但这仍然是读者的练习。

    UPDATE :请注意,此宏会扩展为函数定义,您不应在头文件中定义函数,否则将出现重复的定义错误。有几种解决方案,请选择最佳:

    1. 让您的函数保持静态(static TYPE* get_mystuff_##FIELD(...)。这样,包含您的函数的每个编译单元都将获得该函数的副本。
    2. 将函数的定义移动到mystuff.c文件,并仅在mystuff.h中写入函数原型。您可以手动编写这些原型或为此创建宏:

      #define GET_MYSTUFF_PROTO(TYPE, FIELD) TYPE* get_mystuff_##FIELD(struct mystuff *array, int n);

    3. 通过一些额外的工作,如果你想要一点乐趣,你可以使用X_Macros

    4. mystuff.h

      #ifndef GET_MYSTUFF
      #define GET_MYSTUFF(TYPE, FIELD) \
          TYPE* get_mystuff_##FIELD(struct mystuff *array, int n);
      #endif
      
      GET_MYSTUFF(int, a)
      GET_MYSTUFF(int, b)
      GET_MYSTUFF(int, c)
      

      mystuff.c

      /* include for prototypes */
      #include "mystuff.h"
      
      #undef GET_MYSTUFF
      #define GET_MYSTUFF(TYPE, FIELD) \
      TYPE* get_mystuff_##FIELD(struct mystuff *array, int n) \
      { \
          int i; \
          TYPE *res_array; \
          res_array = malloc(n*sizeof(TYPE)); \
          for(i=0;i<n;i++) { \
              res_array[i] = array[i].FIELD; \
          } \
          return res_array; \
      }
      
      /* include for definitions */
      #include "mystuff.h"
      

答案 1 :(得分:1)

我得出了类似于罗德里戈的结论,最简单的方法是使用宏来宣告你的“吸气剂”,然后你可以像使用它们一样使用它们

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

struct mystuff {
    int a;
    int b;
    int c;
};

#define declare_getstuff_for(f) int* get_mystuff_##f(struct mystuff *array, int n) \
{ \
    int i; \
    int *a_array; \
\
    a_array = malloc(n*sizeof(int)); \
\
    for(i=0;i<n;i++) { \
        a_array[i] = array[i].f;  \
    }  \
    return a_array; \
}

declare_getstuff_for(a)
declare_getstuff_for(b)
declare_getstuff_for(c)


int main(void) {
    int *result1, *result2, *result3;
    struct mystuff array[3];
    struct mystuff el1, el2, el3;
    el1.a = el1.b = el1.c = 1;
    el2.a = el2.b = el2.c = 5;
    el3.a = el3.b = el3.c = 3;

    array[0] = el1;
    array[1] = el2;
    array[2] = el3;

    result1 = get_mystuff_a(array, 3);
    printf("%d, %d, %d\n", result1[0], result1[1], result1[2]);

    result2 = get_mystuff_b(array, 3);
    printf("%d, %d, %d\n", result2[0], result2[1], result2[2]);

    result3 = get_mystuff_c(array, 3);
    printf("%d, %d, %d\n", result3[0], result3[1], result3[2]);

    // Now free your memory :)

    return 0;
}

要记住的相关部分是用于生成函数名称的令牌粘贴运算符##,通常的宏替换和多行\标记。

除此之外:请注意,像这样的代码中的错误通常很难调试。始终更喜欢干净,可维护的代码,并在必要时使用宏。

使用审核:)

尝试一下:http://ideone.com/bbYsJK