January 15, 2013

Keyword arguments in C

Posted in Software at 06:03 by graham

This is valid C nowadays:

my_func(.username="Bob", .is_admin=true);

I found it in 21st Century C. It requires a macro and a structure, and relies on three features introduced in C99.

#include <stdio.h>      // printf
#include <stdbool.h>    // bool - there's a bool type now

// Macro that turns the kwargs into an struct
#define my_func(...) my_func_base(\
    (struct user){.is_admin=false, __VA_ARGS__});

struct user {
    char *username;
    bool is_admin;

// The actual function - and yes there's single line comments too
void my_func_base(struct user u) {
    printf("Hello %s\n", u.username);

int main(int argc, char *argv[]) {
    my_func(.username="Bob", .is_admin=true);

The three new features introduced in C99 that make this possible are:

  • Compound literals which allow my_user = (user) {"Bob", true}.
  • Designated initializers which give us struct user my_user = {.username="Test", .is_admin=true}
  • Variadic macros which allow #define‘s to take ... as a parameter and have it substituted wherever __VA_ARGS__ appears in that macro.

All the keyword arguments are optional, because compound literal rules state that any unspecified arguments are set to zero / null of the appropriate type.

We even have default arguments, like the .is_admin=false in the macro above, because designated initializer rules state that if the argument is repeated, the last argument wins.