Many times I want a function to receive a variable number of arguments, terminated by NULL, for instance
#define push(stack_t stack, ...) _push(__VARARG__, NULL);
func _push(stack_t stack, char *s, ...) {
va_list args;
va_start(args, s);
while (s = va_arg(args, char*)) push_single(stack, s);
}
Can I instruct gcc or clang to warn if foo receives non char*
variables? Something similar to __attribute__(format)
, but for multiple arguments of the same pointer type.
I know you're thinking of using __attribute__((sentinel))
somehow, but this is a red herring.
What you want is to do something like this:
#define push(s, args...) ({ \
char *_args[] = {args}; \
_push(s,_args,sizeof(_args)/sizeof(char*)); \
})
which wraps:
void _push(stack_t s, char *args[], int argn);
which you can write exactly the way you would hope you can write it!
Then you can call:
push(stack, "foo", "bar", "baz");
push(stack, "quux");
I can only think of something like this:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct tArg
{
const char* Str;
struct tArg* Next;
} tArg;
tArg* Arg(const char* str, tArg* nextArg)
{
tArg* p = malloc(sizeof(tArg));
if (p != NULL)
{
p->Str = str;
p->Next = nextArg;
}
else
{
while (nextArg != NULL)
{
p = nextArg->Next;
free(nextArg);
nextArg = p;
}
}
return p;
}
void PrintR(tArg* arg)
{
while (arg != NULL)
{
tArg* p;
printf("%s", arg->Str);
p = arg->Next;
free(arg);
arg = p;
}
}
void (*(*(*(*(*(*(*Print8
(const char* Str))
(const char*))
(const char*))
(const char*))
(const char*))
(const char*))
(const char*))
(const char*)
{
printf("%s", Str);
// There's probably a UB here:
return (void(*(*(*(*(*(*(*)
(const char*))
(const char*))
(const char*))
(const char*))
(const char*))
(const char*))
(const char*))&Print8;
}
int main(void)
{
PrintR(Arg("HELLO", Arg(" ", Arg("WORLD", Arg("!", Arg("\n", NULL))))));
// PrintR(Arg(1, NULL)); // warning/error
// PrintR(Arg(&main, NULL)); // warning/error
// PrintR(Arg(0, NULL)); // no warning/error
// PrintR(Arg((void*)1, NULL)); // no warning/error
Print8("hello")(" ")("world")("!")("\n");
// Same warning/error compilation behavior as with PrintR()
return 0;
}
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