As it happens, I have an implementation (two implementations, actually) of that function here at line 77 or so. It's just a simple wrapper designed to make calling the function easier; there are more efficient solutions but it doesn't usually make much difference.
/* Like GNU asprintf, but returns the resulting string buffer;
 * it is the responsibility of the caller to freee the buffer
 */
char* concatf(const char* fmt, ...);
The first one relies on vasprintf, which is a non-standard function which is part of Gnu glibc:
char* concatf(const char* fmt, ...) {
  va_list args;
  char* buf = NULL;
  va_start(args, fmt);
  int n = vasprintf(&buf, fmt, args);
  va_end(args);
  if (n < 0) { free(buf); buf = NULL; }
  return buf;
}
The second one relies on vsnprintf, which is a Posix-standard interface but was incorrectly implemented in some older standard C library implementations (glibc until version 2.0.6, for example.)
char* concatf(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  char* buf = NULL;
  int n = vsnprintf(NULL, 0, fmt, args);
  va_end(args);
  if (n >= 0) {
    va_start(args, fmt);
    buf = malloc(n+1);
    if (buf) vsnprintf(buf, n+1, fmt, args);
    va_end(args);
  }
  return buf;
}
Feel free to use them as you need them. They're not particularly profound.
For gcc (and, I think, clang), you can declare the function as:
char* concatf(const char *fmt, ...)
      __attribute__ ((format (printf, 1, 2)));
which will enable the compiler to check the validity of the format string, as it does with printf