<stdarg.h> es un archivo de cabecera en la biblioteca estándar de C del lenguaje de programación C que permite que las funciones acepten un número indefinido de argumentos . [ 1 ] Proporciona facilidades para recorrer una lista de argumentos de función de número y tipo desconocidos. C++ proporciona esta funcionalidad en el archivo de cabecera<cstdarg>.
El contenido de <stdarg.h>se utiliza normalmente en funciones variádicas , aunque también puede utilizarse en otras funciones (por ejemplo, vprintf) llamadas por funciones variádicas.
Creación de funciones variádicas
Las funciones variádicas son funciones que pueden tomar un número variable de argumentos y se declaran con puntos suspensivos en lugar del último parámetro. Un ejemplo de dicha función es printf. Respectivamente, las declaraciones y definiciones se realizan de manera similar a como se muestra a continuación.
comprobación de enteros ( entero a , doble b , ...);int comprobar ( int a , double b , ...) { // ... }Según el estándar, las funciones varádicas sin parámetros con nombre no están permitidas en C17 y anteriores, pero en C++ y C23 [ 2 ] dicha declaración está permitida.
En C , debe ir precedida de una coma si se especifica un parámetro con nombre, mientras que en C++ era opcional hasta C++26, cuando se dejó de usar.
Algunas declaraciones de funciones al estilo C de K&R no utilizan puntos suspensivos. [ 3 ]
tipos de stdarg.h
macros de stdarg.h
Acceso a los argumentos
Según el estándar, para acceder a los argumentos sin nombre se puede hacer a través de una variable de tipo va_listen la función variádica, con la macro va_starttambién proporcionada como el último parámetro con nombre de la función. En C23 el segundo argumento es opcional y no se evaluará. [ 2 ] Después de esto, cada invocación de la va_argmacro produce el siguiente argumento. El primer argumento de va_arges el va_listy el segundo es el tipo del siguiente argumento pasado a la función. Como último paso, la va_endmacro debe llamarse en el va_listantes de que la función regrese. Tenga en cuenta que no es necesario leer todos los argumentos.
C99 proporciona una macro adicional, va_copy, que puede duplicar el estado de un va_list. La invocación de la macro va_copy(va2, va1)copia va1en va2.
No existe un método definido para contar o clasificar los argumentos sin nombre que se pasan a la función variádica. La función simplemente debe determinar esto de alguna manera, cuyos medios varían. Las convenciones comunes incluyen:
- Uso de una cadena de formato similar
printfa oscanfcon especificadores incrustados que indican los tipos de argumentos. - Un valor centinela al final de los argumentos variádicos.
- Un argumento de conteo que indica el número de argumentos variádicos.
Pasar argumentos sin nombre a otras llamadas
Como el tamaño de la lista de argumentos sin nombre generalmente se desconoce, las convenciones de llamada empleadas por la mayoría de los compiladores no permiten determinar el tamaño del bloque de argumentos sin nombre al que apunta va_listdentro de la función receptora. Como resultado, tampoco hay una forma confiable y genérica de pasar los argumentos sin nombre a otra función variádica. Incluso cuando es posible determinar el tamaño de la lista de argumentos por medios indirectos (por ejemplo, analizando la cadena de formato de fprintf()), no hay una forma portable de pasar el número de argumentos determinado dinámicamente a la llamada variádica interna, ya que el número y el tamaño de los argumentos pasados a dichas llamadas generalmente deben conocerse en tiempo de compilación. Hasta cierto punto, esta restricción puede aliviarse empleando macros variádicas en lugar de funciones variádicas. Además, la mayoría de los procedimientos de la biblioteca estándar proporcionan vversiones alternativas con el prefijo que aceptan una referencia a la lista de argumentos sin nombre (es decir, una variable inicializada va_list) en lugar de la lista de argumentos sin nombre en sí. Por ejemplo, vfprintf()es una versión alternativa de que fprintf()espera una va_listen lugar de la lista de argumentos sin nombre real. Por lo tanto, una función variádica definida por el usuario puede inicializar una va_listvariable va_starty pasarla a una función de la biblioteca estándar adecuada, pasando así la lista de argumentos sin nombre por referencia en lugar de por valor. Dado que no existe una forma fiable de pasar listas de argumentos sin nombre por valor en C, proporcionar funciones API variádicas sin proporcionar también funciones equivalentes que acepten va_listargumentos sin nombre se considera una mala práctica de programación.
Seguridad de tipo
Algunas implementaciones de C proporcionan extensiones que permiten al compilador comprobar el uso correcto de cadenas de formato y centinelas. Sin estas extensiones, el compilador normalmente no puede comprobar si los argumentos sin nombre pasados son del tipo que espera la función, ni convertirlos al tipo requerido. Por lo tanto, se debe tener cuidado para garantizar la corrección en este sentido, ya que se produce un comportamiento indefinido si los tipos no coinciden. Por ejemplo, si el tipo esperado es int*, entonces se debe pasar un puntero nulo como (int*)NULL. Escribir solo NULLdaría como resultado un argumento de tipo into void*, ninguno de los cuales es correcto. Otra consideración son las promociones de argumentos predeterminadas que se aplican a los argumentos sin nombre. Un floatse promoverá automáticamente a un double. Del mismo modo, los argumentos de tipos más estrechos que un intse promoverán a into unsigned int. La función que recibe los argumentos sin nombre debe esperar el tipo promovido.
GCC tiene un atributo que verifica los argumentos pasados: . [ 4 ] El atributo de formato especifica que una función toma argumentos de estilo que deben verificarse en cuanto a su tipo con respecto a una cadena de formato. Por ejemplo, la declaración:[[gnu::format(style,format_index,first_to_check)]]printfscanfstrftimestrfmon
[[ gnu :: format ( printf , 2 , 3 )]] extern int my_printf ( void * obj , const char * fmt , ...);hace que el compilador compruebe que los argumentos en las llamadas sean my_printfcoherentes con el printfargumento de cadena de formato de estilo my_format. [ 5 ]
Ejemplo
#include <stdio.h> #include <stdarg.h>// Obtener la suma de las variables int sum ( int count , ...) { va_list ap ; int total = 0 ; va_start ( ap , count ); for ( int i = 0 ; i < count ; i ++ ) { total += va_arg ( ap , int ); } va_end ( ap ); return total ; }int main ( void ) { printf ( "%i" , sum ( 2 , 1 , 3 )); return 0 ; }Este programa debería generar la siguiente salida:
4
<varargs.h>
Las versiones obsoletas de POSIX definieron el encabezado heredado <varargs.h>, que data de antes de la estandarización de C y proporciona una funcionalidad similar a <stdarg.h>. Este encabezado no forma parte ni de ISO C ni de POSIX. El archivo, tal como se define en la segunda versión de la Especificación Única de UNIX , simplemente contiene toda la funcionalidad de C89 <stdarg.h>, con las excepciones de que:
- no se puede utilizar en las definiciones estándar de estilo nuevo de C
- El argumento dado puede omitirse (el estándar C requiere al menos un argumento).
La interfaz también es diferente. Por printargsejemplo, en su lugar se escribiría:
#include <stdio.h> #include <varargs.h>/** * Esto es K&R C (pre-C89). * No hay tipo "void"; use un retorno int implícito. */ printargs ( arg1 , va_alist ) va_dcl /* ¡sin punto y coma aquí! */ { va_list ap ; int i = 0 ;va_start ( ap ); /* ¡Solo se proporciona va_list! */ for ( i = arg1 ; i >= 0 ; i = va_arg ( ap , int )) { printf ( "%d" , i ); } va_end ( ap ); putchar ( '\n' ); return ; }y se llama de la misma manera.
varargs.hrequiere definiciones de funciones de estilo antiguo debido a la forma en que funciona la implementación. [ 6 ] Por el contrario, no es posible mezclar definiciones de funciones de estilo antiguo con stdarg.h.
Referencias
- ↑ "IEEE Std 1003.1
stdarg.h" . Consultado el 4 de julio de 2009 . - 1 2 Gilding, Alex; Meneide, JeanHeyd (2022-04-15). "WG14-N2975 : Relajar los requisitos para las listas de parámetros variádicos, v3" (PDF) .
- ↑ "Definiciones de funciones de estilo antiguo" . Lenguaje GNU C. 2007. Consultado el 15 de noviembre de 2024 .
- ↑ Michael Kerrisk (16 de enero de 2026). "gnu::format(3attr - Página del manual de Linux") . man7.org . man7.
- ↑ "5.27 Extensiones a la familia de lenguajes C - Declaración de atributos de funciones" . Consultado el 3 de enero de 2009 .
- ↑ "Especificación única de UNIX " . Consultado el 1 de agosto de 2007 .
varargs.h
- Encabezados de la biblioteca estándar de C