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, 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.