preprocessor-toolchain · intermediate · ~15 min
Combine preprocessor variadic patterns with runtime vsnprintf formatting and bounds checking.
C99 variadic macros (... and __VA_ARGS__) enable flexible logging frameworks that accept variable numbers of formatting arguments. Defensive formatters route variable arguments through vsnprintf with buffer boundary checks.
Implement:
int log_message_formatted(char *buf, size_t cap, const char *prefix, const char *fmt, ...);
buf == NULL, prefix == NULL, fmt == NULL, or cap == 0, return -1."[PREFIX] ".fmt directly after the prefix.cap (including NUL), return -1 without buffer overflow.char out[64];
log_message_formatted(out, sizeof(out), "INFO", "User %s logged in with ID %d", "alice", 42);
// out is: "[INFO] User alice logged in with ID 42"
buf: output buffer; cap: capacity; prefix: tag string; fmt: printf format string; variadic args.
Returns total characters written, or -1 on truncation/invalid arguments.
Must use stdarg.h with vsnprintf. Safe truncation handling.
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
/* Format "[PREFIX] formatted_msg" into buf. Return characters written or -1 on error/truncation. */
int log_message_formatted(char *buf, size_t cap, const char *prefix, const char *fmt, ...) {
(void)buf; (void)cap; (void)prefix; (void)fmt;
return -1;
}
Forgetting va_end; buffer overflow on prefix concatenation; ignoring vsnprintf truncation.
Buffer capacity exact fit succeeds; buffer 1 byte short returns -1; NULL pointers return -1.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.