I like Nate's answer, so don't change your choice, but there is a subtle variation on it using an anonymous union that will allow you to refer to the members of the union directly without the need to use a union tag to reference the member.
This was introduced with the C11 Standard in 6.7.2.1 Structure and union specifiers(p13). It simply provides a bit of syntactical short-hand. For example using an anonymous union within the struct, e.g.
typedef struct { /* struct containing tag and union between int/char[] */
int tag;
union { /* anonymous union allow you to refer */
char str[MAXC]; /* to members as members of the struct */
int number;
};
} mytype;
...
mytype array[] = {{ISSTR, {"helo"}}, {ISINT, {{2}}}, {ISSTR, {"watkins"}}};
Your access to the union members would be:
printf ("The string is: %s\n", array[i].str);
or
printf ("The number is: %d\n", array[i].number);
(with no union tag between the array[i]
and the str
or number
)
Putting it altogether, your example would be:
#include <stdio.h>
#define MAXC 16 /* if you need a constant, #define one (or more) */
enum { ISSTR, ISINT }; /* enum can provide global constants as well */
typedef struct { /* struct containing tag and union between int/char[] */
int tag;
union { /* anonymous union allow you to refer */
char str[MAXC]; /* to members as members of the struct */
int number;
};
} mytype;
int main (void) {
mytype array[] = {{ISSTR, {"helo"}}, {ISINT, {{2}}}, {ISSTR, {"watkins"}}};
int array_len = sizeof array/sizeof *array;
for (int i=0; i<array_len; i++) {
// how to do this in C?
if (array[i].tag == ISSTR) /* if tag ISSTR element is string */
printf ("The string is: %s\n", array[i].str);
else if (array[i].tag == ISINT) /* if ISINT, element holds an int */
printf ("The number is: %d\n", array[i].number);
else
fputs ("As Nate put it, things are horribly wrong...\n", stderr);
}
}
Example Use/Output
$ ./bin/structunion
The string is: helo
The number is: 2
The string is: watkins
Keep in mind this was introduced with C11, in C99 you will not find an anonymous struct or anonymous union (though some compilers did provide by as an extension)