As far as I can tell, there's no way to print out a struct value in C.
i.e., this doesn't fly:
typedef struct {
int a;
double b;
} stype
stype a;
a.a=3;
a.b=3.4;
printf("%z", a);
instead you have to say:
printf("a: %d\n", a.a);
printf("b: %f\n", a.b);
This seems like a perfect place where you could use a macro to save a vast amount of typing for arbitrary structs.
Is the C preprocessor powerful enough to perform this transformation?
I think that the simplest solution (and maybe the most beautiful) is to use a function to print your specific struct.
void display_stype(stype *s)
{
printf("a: %d\n", s->a);
printf("b: %f\n", s->b);
}
If your struct changed, you can adapt in one place your code easily.
I would make two macros, like this:
#define STYPE_FMT "%d %f"
#define STYPE_MEMS(s) (s).a, (s).b
Then you can do something like:
printf("hello %s, stype: " STYPE_FMT "\n", "world", STYPE_MEMS(my_s));
What makes this approach superior to a "print function" for the structure is that you can use the macros with any of the printf
-family functions you like, and combine printing of other data.
You could get even fancier and instead do:
#define STYPE_FMT "%d %.*f"
#define STYPE_MEMS(s) (s).a, 6, (s).b
#define STYPE_MEMS_PREC(s, p) (s).a, (int)(p), (s).b
and then you can use the default precision or choose a custom precision.
Is the C preprocessor powerful enough to perform this transformation?
Yes, it is, but then you have to repeat the entire struct declaration within the macro which kind of defeats the purpose. You could have something like this:
STRUCT_PRINTF(
a
, ( int, a )
( double, b )
);
and then you would need a pretty complex implementation of such macro, with lots and lots of helper macros/functions.
No, the C preprocessor is mostly a textual macro replacement tool. It doesn't know about types and structures of C.
You cannot iterate on struct members in C, either dynamically or statically (nor in C++). There is no reflection in C.
Thus, there is no way to make the preprocessor perform this transformation.
You could make macro for this:
#define PRINT_MEMBER(M) do {printf(#M": %d\n", (int) M;} while(0)
and then print it like this:
PRINT_MEMBER(a.a);
PRINT_MEMBER(b->b);
You might wanna define multiple of these to cover different types (e.g. floats, doubles, print as hex). Unfortunately there is no good workaround for this as C preprecossor has no notion of what types are, e.g. you can't use something like switch(typeof(M)) { case int: printf(.."%d"..; break; ...}
.