Reputation: 1864
Is it possible to store a C data type in a variable?
Something like this:
void* type = (byte*);
Here is a scenario, where I wrote a test case and tried to print out a byte array using certain data types for use in printf, depending on the given parameters:
void print_byteArray(const void* expected, size_t size,
bool asChars, bool asWCharT) {
int iterations;
char* format;
if (asChars) {
iterations = (size / (sizeof (char)));
format = "%c";
} else if (asWCharT) {
iterations = (size / (sizeof (wchar_t)));
format = "%lc";
} else {
iterations = (size / (sizeof (byte)));
format = "%x";
}
int i;
for (i = 0; i < iterations; i++) {
if (asChars) {
printf(format, ((char*) expected)[i]);
} else if (asWCharT) {
printf(format, ((wchar_t*) expected)[i]);
} else {
printf(format, ((byte*) expected)[i]);
}
}
fflush(stdout);
}
This looks like inefficient code. I'd imagine it that one could size-down the for-loop body to a single line:
printf(format, ((type) expected)[i]);
Upvotes: 15
Views: 9277
Reputation: 1922
C is a statically-typed language, so you would have to build your own run-time type system. However, if one just wants to print values of arbitrary data, one can use printf
's %s
and work with temporary string buffers. This will work in some cases where the data you want to print is bounded:
#include <stdlib.h> /* EXIT_ */
#include <stdio.h> /* *printf */
#define PRINT_BUFFERS (4)
struct Foo {
int key;
char value[32];
};
/** Assumes {key} is {[0, 99]} to comply with C90, otherwise use {snprintf}. */
static void Foo_to_string(const struct Foo *foo, char (*const a)[12]) {
sprintf(*a, "%d%.9s", foo->key, foo->value);
}
/** This is more convenient, but lacks generality. */
static const char *Foo_to_static(const struct Foo *foo) {
static char buffers[PRINT_BUFFERS][12];
static unsigned n;
char *const a = buffers[n];
sprintf(a, "%d%.9s", foo->key, foo->value);
n = (n + 1) % PRINT_BUFFERS;
return a;
}
int main(void) {
const struct Foo foo = { 42, "foo" }, bar = { 96, "bar" },
baz = { 13, "baz_abcdefg" };
/* This way is more general. */
char a[12], b[12], c[12];
Foo_to_string(&foo, &a);
Foo_to_string(&bar, &b);
Foo_to_string(&baz, &c);
printf ("Foo: %s; Bar: %s; Baz: %s.\n", a, b, c);
/* This way is convenient, but you have a max number of calls. */
printf("Foo: %s; Bar: %s; Baz: %s.\n", Foo_to_static(&foo),
Foo_to_static(&bar), Foo_to_static(&baz));
return EXIT_SUCCESS;
}
Upvotes: 0
Reputation: 122493
No, there's no such type that can store a type in standard C.
gcc provides a typeof
extension that may be useful. The syntax of using of this keyword looks like sizeof
, but the construct acts semantically like a type name defined with typedef
. See here for detail.
Some more examples of the use of typeof
:
This declares y with the type of what x points to.
typeof (*x) y;
This declares y as an array of such values.
typeof (*x) y[4];
This declares y as an array of pointers to characters:
typeof (typeof (char *)[4]) y;
It is equivalent to the following traditional C declaration:
char *y[4];
To see the meaning of the declaration using typeof, and why it might be a useful way to write, rewrite it with these macros:
#define pointer(T) typeof(T *)
#define array(T, N) typeof(T [N])
Now the declaration can be rewritten this way:
array (pointer (char), 4) y;
Thus, array (pointer (char), 4)
is the type of arrays of 4 pointers to char.
Upvotes: 17