Is it possible to implement static_if in C99?
#define STATIC_IF(COND, ...) \
if (COND) MACRO1(__VA_ARGS__); \
else MACRO2(__VA_ARGS__);
How can I properly implement STATIC_IF(…)
in here? Depending on COND
the arguments either should be passed to MACRO1
or MACRO2
, but the arguments for both macros look differently. COND
is statically testable, something like sizeof (…) > 42
.
#if COND
then #define STATIC_IF MACRO1
… wouldn't work for my use case.In your specific case (if I understand your comments correctly), yes, you can do this.
You can't pass sizeof
to anything in the preprocessor because the preprocessor runs before type information is available. Luckily for you, you don't need sizeof
to count the number of arguments in a statically-written list (X-Y alert!), so this is no obstacle.
Here's one possible implementation using the Order macro library:
#include <stdio.h>
#include <order/interpreter.h>
void oneArg(int a) {
printf("one arg: %d\n", a);
}
void twoArgs(int a, int b) {
printf("two args: %d %d\n", a, b);
}
void threeArgs(int a, int b, int c) {
printf("three args: %d %d %d\n", a, b, c);
}
#define ORDER_PP_DEF_8function_list \
ORDER_PP_CONST(("unused") \
(oneArg) \
(twoArgs) \
(threeArgs))
#define SelectFunction(...) ORDER_PP ( \
8seq_at(8tuple_size(8((__VA_ARGS__))), 8function_list) \
)
#define Overloaded(...) SelectFunction(__VA_ARGS__)(__VA_ARGS__)
int main(void) {
Overloaded(42);
Overloaded(42, 47);
Overloaded(42, 47, 64);
return 0;
}
(This simple case indexes a list by the number of arguments - probably not exactly what you want to do, but enough to get the idea. Order does provide a full range of complex, nonevaluating control structures - if
, cond
, match
, etc. - for more complex decision-making.)
Order is pretty heavyweight: I assume you can do something similar with the much lighter and more realistically-portable P99 (not familiar with it). Order works very well with GCC and adequately well with Clang (Clang will choke on deep recursion or long loops); it is standard, but not all compilers are.
This is not possible, because a condition like sizeof(something)>42
is not static for the preprocessor. The preprocessor is purely textual (in principle, except for arithmetic). It does not know about C or types.
Notice that expression of the condition in #if
is severely constrained.
However, you could use build tricks. For instance, you might have a standalone program like
// generate-sizeof.c
#include <stdio.h>
#include "foo-header.h"
int main(int argc, char**argv) {
const char* headername = NULL;
if (argc<2)
{ fprintf(stderr, "%s: missing header name\n", argv[0]);
exit(EXIT_FAILURE); };
headername = argv[1];
FILE *fh = fopen(headername, "w");
if (!fh) { perror(headername); exit(EXIT_FAILURE); };
fprintf(fp, "// generated file %s\n", headername);
fprintf(fp, "#define SIZEOF_charptr %d\n", (int) sizeof(char*));
fprintf(fp, "#define SIZEOF_Foo %d\n", (int) sizeof(Foo));
fclose (fp);
}
then have a rule like
generated-sizes.h : generate-sizeof foo-header.h
./generate-sizeof generated-sizes.h
in your Makefile
etc etc...
So your build machinery will generate the appropriate headers.
Things become much tricker if you want to cross-compile!
Then you might have an #include "generated-sizes.h"
in your header, and later code
#if SIZEOF_Foo > 42
#error cannot have such big Foo
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With