带有可以是不同结构的参数的函数

时间:2018-02-27 15:27:54

标签: c pointers struct

我试图获得一些复杂的功能,我将在这里简化:

我有几种不同变量的结构:

struct param1 {
int varA;
int varB;
}p1;

struct param2 {
int varX;    
int varY;
int varZ;
}p2;

另一方面,我有一个必须使用这些结构的函数,让我们简化它们只是打印数据:

void function(int type_of_structure, <<struct param>>)

然后,函数应该执行以下操作:切换结构类型,并相应地打印值。

switch(type_of_structure)
{
case 1:
printf("param.varA = %d \n",param.varA);
printf("param.varB = %d \n",param.varB);

case 2:
printf("param.varX = %d \n",param.varX);
printf("param.varY = %d \n",param.varY);
printf("param.varZ = %d \n",param.varZ);
}

我知道可以使用带有void **参数和强制转换的函数在C中完成。但是,我在很多方面都在尝试而没有成功。

我应该如何声明&lt;&gt;在函数中为了能够区分不同类型的结构?

3 个答案:

答案 0 :(得分:5)

使用union,这是真正的方式。

#include <stdio.h>

enum struct_type {
    STRUCT_TYPE_A, STRUCT_TYPE_B
};

struct A {
    int x;
    int y;
};

struct B {
    int x;
    int y;
    int z;
};

union C {
    struct A a;
    struct B b;
};

void
print(enum struct_type type, union C object)
{
    switch (type) {
    case STRUCT_TYPE_A:
        fprintf(stdout, "(x, y) = %d, %d\n", object.a.x, object.a.y);
        break;
    case STRUCT_TYPE_B:
        fprintf(stdout, "(x, y, z) = %d, %d, %d\n", object.b.x, object.b.y, object.b.z);
        break;
    }
}


int
main(void)
{
    union C a = {.a = {1, 2}};
    union C b = {.b = {3, 4, 5}};

    print(STRUCT_TYPE_A, a);
    print(STRUCT_TYPE_B, b);

    return 0;
}

中使用泛型void *指针非常危险。此外,并不意味着具有泛型类型,如果您习惯于考虑泛型,那么处理它很困难,但很明显,当您深入理解其他解决方案时更适合。

注意:恕我直言,此代码可以更加清晰int print_struct_A(FILE *target, const struct A *const object);并在print()函数中调用它们。

答案 1 :(得分:2)

因为您根据&#34;标记&#34;识别结构。 (type_of_structure),您可以使用void *并根据标记对其进行解释:

void function(int type_of_structure, void *arg)
{
    switch(type_of_structure)
    {
    case 1: {
    struct param1 *s1 = arg;
    printf("param.varA = %d \n",s1->varA);
    printf("param.varB = %d \n",s1->varB);
    break;
    }

    case 2: {
    struct param2 *s2 = arg;
    printf("param.varX = %d \n",s2->varX);
    printf("param.varY = %d \n",s2->varY);
    printf("param.varZ = %d \n",s2->varZ);
    break;
    }
    }
}

你打电话给它:

function(type_of_structure, &param);

答案 2 :(得分:2)

尽可能避免强制用户使用正确的枚举器和正确匹配的对象类型调用函数。

如果想冒险进入C11 _Generic,代码可以创建一个宏DO_print(X)来选择正确的打印功能。 <{1}}不需要。

否则我建议代码简单调用结构特定的打印功能。

鉴于结构可能是任意大小,我建议按地址传递它们。

int type_of_structure

使用示例

#include <stdio.h>

typedef struct param1 {
  int varA;
  int varB;
} p1;

typedef struct param2 {
  int varX;
  int varY;
  int varZ;
} p2;

void DO_print_p1(const p1 *o1) {
  printf("param.varA = %d \n",o1->varA);
  printf("param.varB = %d \n",o1->varB);
}

void DO_print_p2(const p2 *o2) {
  printf("param.varX = %d \n",o2->varX);
  printf("param.varY = %d \n",o2->varY);
  printf("param.varZ = %d \n",o2->varZ);
}

#define DO_print(X) _Generic((X), \
  p1 *: DO_print_p1, \
  p2 *: DO_print_p2 \
  )(X)

输出

int main() {
  p1 o1 = { 1,2};
  p2 o2 = { 3, 4,5};
  DO_print(&o1);
  DO_print(&o2);
  return 0;
}

如果代码仍然希望使用通用的param.varA = 1 param.varB = 2 param.varX = 3 param.varY = 4 param.varZ = 5 来实现易于理解的实现,那么请通过包装函数将其隐藏起来直接用户使用/滥用。

void function(int type_of_structure, <<struct param>>)