Please can someone show me a code fragment using the following code. I think I understand the enum, and the union part. But dont get how the enum works in conjunction with the union part. Every other example I have found uses an integer in place of the enum to save the union type that's presently in use. I have tried to comprehend how this works but simply miss whats going on.
struct taggedunion { enum {UNKNOWN, INT, LONG, DOUBLE, POINTER} code; union { int i; long l; double d; void *p; } u; };
If you understand the other examples using an integer, then you'll understand this one using an enum, because an enum is an integer type.
An enum is really just a way of assigning symbolic names to constant integer values; thus
enum {UNKNOWN, INT, LONG, DOUBLE, POINTER}
is almost equivalent to
#define UNKNOWN 0 #define INT 1 #define LONG 2 #define DOUBLE 3 #define POINTER 4
The difference is that enum is part of the 'C' language, but #defines are handled entirely by the preprocessor - so the compiler never gets to see the symbolic names. One advantage this gives is the opportunity for the compiler to include the symbolic names in its debug info - I don't know if Keil's ARM tools take advantage of this, but C51 doesn't :-(
See c-faq.com/.../enumvsdefine.html
Again, this is standard 'C' stuff - nothing specifically to do with ARM, Keil, or embedded systems.
"Every other example I have found uses an integer in place of the enum ..."
I was taking that to mean that you understood the integer versions.
#include <stdio.h> struct taggedunion { enum {UNKNOWN, INT, LONG, DOUBLE, POINTER} code; union { int i; long l; double d; void *p; } u; }; void print_vr(struct taggedunion *vr /* Ptr to variant record */) { switch (vr->code) { case INT: printf("i: %d\n", vr->u.i); break; case LONG: printf("l: %ld\n", vr->u.l); break; case DOUBLE: printf("d: %lf\n", vr->u.d); break; case POINTER: printf("p: %p\n", vr->u.p); break; case UNKNOWN: default: printf("Type unknown\n"); break; } }