estándar.h

Archivo de encabezado para programas en C

stdarg.hes un encabezado en la biblioteca estándar 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 encabezado cstdarg.

Los contenidos de stdarg.hse utilizan normalmente en funciones variádicas , aunque pueden usarse en otras funciones (por ejemplo, vprintf) llamadas por funciones variádicas.

Declaración de funciones variádicas

Las funciones variádicas son funciones que pueden tomar una cantidad variable de argumentos y se declaran con puntos suspensivos en lugar del último parámetro. Un ejemplo de este tipo de función es printf. Una declaración típica es

int comprobar ( int a , doble b , ...);     

Las funciones variádicas deben tener al menos un parámetro nombrado, así, por ejemplo,

char * incorrecto (...); 

no está permitido en C17 y anteriores, pero en C++ y C23 [2] tal declaración está permitida.

En C, una coma debe preceder a los puntos suspensivos si se especifica un parámetro con nombre, mientras que en C++ es opcional.

Definición de funciones variádicas

La misma sintaxis se utiliza en una definición:

función larga ( char , doble , int , ...);    función larga ( char a , doble b , int c , ...) { /* ... */ }        

Es posible que no aparezcan puntos suspensivos en las definiciones de funciones de estilo antiguo.

Tipos de stdarg.h

NombreDescripciónCompatibilidad
va_listtipo para iterar argumentosC89

macros stdarg.h

NombreDescripcióncompatibilidad
va_startComience a iterar argumentos con unva_listC89
va_argRecuperar un argumentoC89
va_endGratis ava_listC89
va_copyCopiar el contenido de uno va_lista otroC99

Accediendo 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 macro va_starttambién proporcionada como el último parámetro nombrado de la función. En C23 el segundo argumento es opcional y no será evaluado [2] . Después de esto, cada invocación de la va_argmacro produce el siguiente argumento. El primer argumento va_arges va_listy el segundo es el tipo del siguiente argumento pasado a la función. Como último paso, la va_endmacro debe ser llamada en 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 debería determinar esto de alguna manera, cuyos medios varían. Las convenciones comunes incluyen:

  • Uso de una cadena de formato similar printfa o scanfcon especificadores integrados que indican 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

Debido a que 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 genérica y confiable de reenviar 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 portátil 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 el momento de la compilación. Hasta cierto punto, esta restricción se puede relajar 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 prefijo - que aceptan una referencia a la lista de argumentos sin nombre (es decir, una va_listvariable inicializada) en lugar de la lista de argumentos sin nombre en sí. Por ejemplo, vfprintf()es una versión alternativa de fprintf()esperar a 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 mediante va_starty pasarla a una función de biblioteca estándar adecuada, pasando de hecho la lista de argumentos sin nombre por referencia en lugar de hacerlo por valor. Debido a que no existe una forma confiable 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_listen su lugar se considera una mala práctica de programación.

Tipo de seguridad

Algunas implementaciones de C proporcionan extensiones de C que permiten al compilador verificar el uso correcto de cadenas de formato y centinelas. Salvo estas extensiones, el compilador generalmente no puede verificar si los argumentos sin nombre pasados ​​son del tipo que la función espera, o 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. A floatse promoverá automáticamente a a double. Del mismo modo, los argumentos de tipos más estrechos que an intse promoverán a into unsigned int. La función que recibe los argumentos sin nombre debe esperar el tipo promocionado.

GCC tiene una extensión que verifica los argumentos pasados:

format(archetype, string-index, first-to-check)

El atributo de formato especifica que una función acepta argumentos printf, o style que deben comprobarse en función del tipo con una cadena de formato. Por ejemplo, la declaración scanf:strftimestrfmon

extern int my_printf ( void * mi_objeto , const char * mi_formato , ...) __atributo__ (( formato ( printf , 2 , 3 )));            

hace que el compilador verifique los argumentos en las llamadas a my_printfpara verificar su coherencia con el printfformato de estilo de la cadena de argumentos my_format.

—  "5.27 Extensiones de la familia de lenguajes C - Declaración de atributos de funciones" . Consultado el 3 de enero de 2009 .

Ejemplo

#incluir <stdio.h> #incluir <stdarg.h>  /* imprime todos los argumentos uno a uno hasta que se vea un argumento negativo;  se supone que todos los argumentos son de tipo int */ void printargs ( int arg1 , ...) { va_list ap ; int i ;        va_start ( ap , arg1 ); para ( i = arg1 ; i >= 0 ; i = va_arg ( ap , int )) printf ( "%d" , i ); va_end ( ap ); putchar ( '\n' ); }                 int main ( void ) { imprimirargs ( 5 , 2 , 14 , 84 , 97 , 15 , -1 , 48 , -1 ); imprimirargs ( 84 , 51 , -1 , 3 ); imprimirargs ( -1 ); imprimirargs ( 1 , -1 ); devolver 0 ; }                   

Este programa produce el siguiente resultado:

5 2 14 84 97 1584 511

Para llamar a otras funciones var args desde dentro de su función (como sprintf), debe usar la versión var arg de la función (vsprintf en este ejemplo):

void MyPrintf ( const char * format , ...) { va_list args ; char buffer [ BUFSIZ ];         va_start ( argumentos , formato ); vsnprintf ( búfer , tamaño del búfer , formato , argumentos ); va_end ( argumentos ); FlushFunnyStream ( búfer ); }        

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 es parte 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 que:

  • No se puede utilizar en definiciones de nuevo estilo estándar de C.
  • El argumento dado puede omitirse (el estándar C requiere al menos un argumento)

La interfaz también es diferente. Por printargsejemplo, se podría escribir:

#include <stdio.h> #include <varargs.h>  /* No hay ningún tipo "void"; use un retorno int implícito. */ printargs ( arg1 , va_alist ) va_dcl /* ¡aquí no hay punto y coma! */ { va_list ap ; int i ;        va_start ( ap ); /* ¡solo se proporciona la 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. [3] Por el contrario, no es posible mezclar definiciones de funciones de estilo antiguo con stdarg.h.

Referencias

  1. ^ "IEEE Std 1003.1 stdarg.h" . Consultado el 4 de julio de 2009 .
  2. ^ ab Gilding, Alex; Meneide, JeanHeyd (15 de abril de 2022). "WG14-N2975: Relajar requisitos para listas de parámetros variádicos, v3" (PDF) .
  3. ^ "Especificación única de UNIX varargs.h" . Consultado el 1 de agosto de 2007 .
Retrieved from "https://en.wikipedia.org/w/index.php?title=Stdarg.h&oldid=1254140769"