char *ptr = NULL;
size_t size = 0;
FILE *fp = open_memstream(&ptr, &size);
Now you can use fp with stdio functions and access the "printed" output via ptr. The buffer is grown automatically and should be freed after fcloseing the stream.
open_memstream is not standard C but specified by POSIX.1-2008. There's an ISO C TR about it though.
For systems, where open_memstream isn't available (like macOS), you can implement it using fopencookie or funopen, which allow you to define your own fread, fwrite, fseek and fclose functions, which will be called while operating on the stream. Both aren't standardized (first is a GNU extension, second is BSD-specific).
You could use BSD libc's implementation on such systems.
For systems that only implement the API mandated by the C standard, you're out of luck. Best you can do is having the output written into a tempfile (Maybe kept in ramfs or similar) and then read from that.
You should only do this if you are interacting with an API that uses FILE IO though. If that's not a requirement consider using std::stringstream or similar instead.