Jeśli masz kod log_out(), przepisz go. Najprawdopodobniej możesz:
static FILE *logfp = ...;
void log_out(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(logfp, fmt, args);
va_end(args);
}
Jeśli potrzebne są dodatkowe informacje logowania, można je wydrukować przed lub po wyświetlonym komunikacie. Oszczędza to alokację pamięci i wątpliwe rozmiary buforów i tak dalej i tak dalej. Prawdopodobnie musisz zainicjować logfpdo zera (wskaźnik zerowy) i sprawdzić, czy jest pusty, i odpowiednio otworzyć plik dziennika - ale kod w istniejącym i tak log_out()powinien sobie z tym radzić.
Zaletą tego rozwiązania jest to, że można je po prostu nazwać tak, jakby to był wariant printf(); w rzeczywistości jest to niewielki wariant printf().
Jeśli nie masz kodu log_out(), zastanów się, czy możesz go zastąpić wariantem, takim jak opisany powyżej. To, czy możesz użyć tej samej nazwy, będzie zależeć od struktury aplikacji i ostatecznego źródła bieżącej log_out()funkcji. Jeśli znajduje się w tym samym pliku obiektowym, co inna niezbędna funkcja, musiałbyś użyć nowej nazwy. Jeśli nie możesz dowiedzieć się, jak dokładnie to powtórzyć, będziesz musiał użyć jakiegoś wariantu, takiego jak podane w innych odpowiedziach, który przydziela odpowiednią ilość pamięci.
void log_out_wrapper(const char *fmt, ...)
{
va_list args;
size_t len;
char *space;
va_start(args, fmt);
len = vsnprintf(0, 0, fmt, args);
va_end(args);
if ((space = malloc(len + 1)) != 0)
{
va_start(args, fmt);
vsnprintf(space, len+1, fmt, args);
va_end(args);
log_out(space);
free(space);
}
/* else - what to do if memory allocation fails? */
}
Oczywiście teraz wywołujesz log_out_wrapper()zamiast log_out()- ale alokacja pamięci i tak dalej jest wykonywana raz. Zastrzegam sobie prawo do nadmiernego przydzielania miejsca o jeden niepotrzebny bajt - nie sprawdziłem dwukrotnie, czy długość zwracana przez vsnprintf()zawiera kończący null, czy nie.