Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Named parameters using a struct.

    struct calculate_args {
        int x, y;
        enum {add=0, sub} operator;
    };

    int calculate_func(struct calculate_args args) {
        if (args.operator == add)
            return args.x + args.y;
        else
            return args.x - args.y;
    }

    #define calculate(...) calculate_func((struct calculate_args){__VA_ARGS__})
Now you can combine positional and named parameters or omit them.

    calculate(1, 3); // 4
    calculate(8, 3, .operator=sub); // 5
    calculate(.operator=sub, .y=7); // -7
Works very well in cases where there is a lot of parameters that default to 0. Keep in mind that you still need to know how structs work and you lose compile-time error detection.



In a similar spirit, overloading functions based on the number of parameters. Even works with tcc.

    #include <stdio.h>
    #define CONCAT2(a, b) a##b
    #define CONCAT(a, b) CONCAT2(a, b)
    #define COUNT_ARGS2(a0, a1, a2, a3, a4, a5, a6, a7, a8, N, ...) N
    #define COUNT_ARGS(...) COUNT_ARGS2(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
    #define foo(...) CONCAT(foo_, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__)

    void foo_1(const char *a){
        printf("one arg: %s\n", a);
    }

    void foo_2(int a, int b){
        printf("two args: %i and %i\n", a, b);
    }

    int main(){
        foo("asdf");
        foo(314159, 271828);
    }
Small gotcha: Does not work with zero parameters, but functions with zero parameters probably mess with global state and that's evil anyway.


If other people use and debug your code please consider NOT using “#define” meta programming. They are a nightmare to debug.


This!

I just wanted to post it, but you already did. :-)




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: