Tengo la siguiente función de registro
void log_error(char * file_name, int line_num, int err_code) { printf("%s:%d:%s\n", file_name, line_num, get_err_str(err_code)); }Quiero cambiar esto para tener la opción de pasar una cadena de formato personalizado y argumentos para obtener información adicional, algo así como
void log_error(char * file_name, int line_num, int err_code, ...) { va_list ptr; char * fmt; printf("%s:%d:%s", file_name, line_num, get_err_str(err_code)); va_start(ptr, err_code); fmt = va_arg(ptr, char *); vprintf(fmt, ptr); printf("\n"); } pero no quiero forzar el paso de esta información adicional, por lo que es posible que no obtenga fmt y los argumentos adicionales requeridos que pueden causar que el código falle, ¿hay alguna manera de verificar si hay argumentos variados antes de intentar acceder a ellos? O la única opción para mi caso de uso es definir 2 funciones diferentes, así
void log_error(char * file_name, int line_num, int err_code) { printf("%s:%d:%s\n", file_name, line_num, get_err_str(err_code)); } void log_error(char * file_name, int line_num, int err_code, const char * fmt, ...) { va_list ptr; printf("%s:%d:%s", file_name, line_num, get_err_str(err_code)); va_start(ptr, err_code); vprintf(fmt, ptr); printf("\n"); va_end(ptr); }No puede verificar los argumentos variádicos en las funciones sin al menos un argumento no variádico que le diga lo que está sucediendo, pero PUEDE usar una macro variadica que se expande a la llamada de función variadica "correcta". Dado que probablemente ya esté utilizando una macro para proporcionar __FILE__ y __LINE__ , probablemente pueda hacer algo como:
// this is the function that will be called by the macro void log_error_func(char * file_name, int line_num, int err_code, const char *fmt, ...); // this is the macro that will be used to log #define log_error(CODE, ...) log_error_func(__FILE__, __LINE__, CODE, "" __VA_ARGS__)Ahora puedes usar cosas como
log_error(42, "this error has args: %d, %d, %d", 1, 2, 3);así como
log_error(5); /* no args here */ y funcionarán como cabría esperar. El uso de "" en una macro como esta requiere que el formato arg (si está presente) sea una cadena literal, por lo que la cadena vacía se antepondrá correctamente.
Su función no tiene forma de saber si se ha pasado o no una cadena de formato. Entonces, lo mejor que puede hacer es convertirlo en un parámetro explícito.
void log_error(char * file_name, int line_num, int err_code, char * fmt, ...) { va_list ptr; printf("%s:%d:%s", file_name, line_num, get_err_str(err_code)); va_start(ptr, fmt); vprintf(fmt, ptr); va_end(ptr); printf("\n"); }Para una función como esta, esperaría que se pasara una cadena de mensaje.
¿Hay alguna forma de verificar si hay argumentos variados antes de intentar acceder a ellos?
No.
la única opción para mi caso de uso es definir 2 funciones diferentes, así
En general, sí, o similar.
Puede convertir log_error en una macro y sobrecargar la macro en la cantidad de argumentos. 3 argumentos irían a la primera versión, más irían a la variádica.