我想不出任何使用未定义行为或非常奇怪的构造的好方法。而且你想要不同类型的字段这一事实并没有让它变得更容易。
如果我想编写这样的代码(我不想),我可能会这样做。
void *get_attr(struct Student *student, int field)
{
switch(field) {
case 0 : return (void*)&student->regNumber;
case 1 : return (void*)&student->fName;
case 2 : return (void*)&student->lName;
case 3 : return (void*)&student->email;
case 4 : return (void*)&student->phoneNumber;
case 5 : return (void*)&student->age;
}
return NULL;
}
然后你可以像这样使用它:
int main()
{
struct Student s = { "xxx333", "Jonny", "BGood", "my@email.com", 12345, 22 };
printf ("%s\n%s\n%s\n%s\n%d\n%d\n",
(char*)get_attr(&s, 0),
(char*)get_attr(&s, 1),
(char*)get_attr(&s, 2),
(char*)get_attr(&s, 3),
*(int*)get_attr(&s, 4),
*(short*)get_attr(&s, 5)
);
}
自然而然地,我没有看到绕过这些演员的好方法。一种方法,但不一定是好方法,是这样做:
union attr_field {
char *c;
int *i;
short *s;
};
enum attr_type { CHAR, INT, SHORT };
struct attr {
union attr_field attr;
enum attr_type type;
};
struct attr get_attr2(struct Student *student, int field)
{
struct attr ret;
switch(field) {
case 0 : ret.attr.c = student->regNumber; ret.type = CHAR; break;
case 1 : ret.attr.c = student->fName; ret.type = CHAR; break;
case 2 : ret.attr.c = student->lName; ret.type = CHAR; break;
case 3 : ret.attr.c = student->email; ret.type = CHAR; break;
case 4 : ret.attr.i = &student->phoneNumber; ret.type = INT; break;
case 5 : ret.attr.s = &student->age; ret.type = SHORT; break;
}
return ret;
}
void print_attr(struct attr a)
{
switch(a.type) {
case CHAR: printf("%s\n", a.attr.c); break;
case INT: printf("%d\n", *a.attr.i); break;
case SHORT: printf("%d\n", *a.attr.s); break;
}
}
int main()
{
struct Student s = { "xxx333", "Jonny", "BGood", "my@email.com", 12345, 22 };
for(int i=0; i<6; i++) {
struct attr a = get_attr2(&s, i);
print_attr(a);
}
}
请注意,我有时使用结构,有时使用指向结构的指针作为函数的参数。选择不是出于任何特殊原因。它只是碰巧是这样的。你可以做任何一种方式,两者都有其优点和缺点。如果性能是一个问题,我会寻求指针。工会也是一样。我本可以选择一个 char 数组并改用 strncpy。我本可以跳过 int 和 short 的指针。在这里,我的想法是,如果所有工会成员都是指针,那就更清楚了。但是你必须对这一切做出你自己的决定。如果您使用指针,在适当的情况下使用 const 限定符可能是明智之举。
如果你真的想这样做,我想你可以这样做:
void *attribs[6];
attribs[0] = (void*)s.regNumber;
printf("%s", (char*)attribs[0]);
这可以与上述技术结合使用。比如
struct attr attribs[6];
for(int i=0; i<6; i++)
attribs[i] = get_attr2(&s, i);