There's nothing wrong with the other answers, but if you'd prefer a solution more portable than `asprinf()` and a bit less cumbersome than Jerry Coffin's vsnprintf() helper function [solution](https://codereview.stackexchange.com/a/223101/51483), consider this variable length macro solution:


    #define FOO_ASPRINTF(_str, ...) /* replace FOO with your codebase's prefix */ \
    do { \
        int byte_c = snprintf(NULL, 0, __VA_ARGS__); \
        (_str) = malloc(byte_c + 1); \
        if (!(_str)) { \
            FOO_MALLOC_ERR; /* should depend on your codebase's malloc() policy */ \
        } \
        sprintf(_str, __VA_ARGS__); \
    } while (0)

Which in OP's case would be invoked like this:

    char * buff = NULL;
    CG_ASPRINTF(buff,
        "%lld %f %f %f %f %f %f %f %f %f %f",
        state->last_update_time,
        p->health,
        p->max_health,
        p->satiation,
        p->max_satiation,
        s->milliseconds_per_tick,
        s->hunger_pain_per_tick,
        s->hunger_per_tick,
        s->satiated_heal_per_tick,
        s->pain_per_wrong_answer,
        s->satiation_per_right_answer
    );

Some people might be allergic to macros, but in this case it allows easy implementation, avoids any overhead, and is perfectly portable.