stdarg.h


De Wikipedia, la enciclopedia libre
  (Redirigido desde la copia de Va )
Saltar a navegación Saltar a búsqueda


stdarg.hes una cabecera en la biblioteca estándar de C del lenguaje de programación C que permite a las funciones que acepten un número indefinido de argumentos . [1] Proporciona facilidades para recorrer una lista de argumentos de función de tipo y número desconocido. C ++ proporciona esta funcionalidad en el encabezado cstdarg.

El contenido de stdarg.hse usa típicamente en funciones variadas , aunque pueden usarse en otras funciones (por ejemplo, vprintf) llamadas por funciones variadas.

Declarar funciones variadas

Las funciones variables 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 tal función es printf. Una declaración típica es

int  check ( int  a ,  double  b ,  ...);

Las funciones variables deben tener al menos un parámetro con nombre, por ejemplo,

char  * incorrecto (...);

no está permitido en C. (En C ++, esta declaración está permitida). En C, una coma debe preceder a los puntos suspensivos; en C ++, es opcional.

Definición de funciones variadas

Se utiliza la misma sintaxis en una definición:

long  func ( char ,  double ,  int ,  ...); func long ( char  a ,  double  b ,  int  c ,  ...) {  / * ... * / }

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

tipos stdarg.h

macros stdarg.h

Accediendo a los argumentos

Para acceder a los argumentos sin nombre, se debe declarar una variable de tipo va_listen la función variadic. A va_startcontinuación, se llama a la macro con dos argumentos: el primero es la variable declarada del tipo va_list, el segundo es el nombre del último parámetro nombrado de la función. Después de esto, cada invocación de la va_argmacro produce el siguiente argumento. El primer argumento de va_arges the va_listy el segundo es el tipo del siguiente argumento que se pasa a la función. Finalmente, se va_enddebe llamar a la macro va_listantes de que regrese la función. (No es necesario leer todos los argumentos).

C99 proporciona una macro adicional va_copy, que puede duplicar el estado de un va_list. La macro invocación se va_copy(va2, va1)copia va1en va2.

No hay ningún mecanismo definido para determinar el número o los tipos de argumentos sin nombre que se pasan a la función. La función simplemente se requiere para saber o determinar esto de alguna manera, cuyos medios varían. Las convenciones comunes incluyen:

  • Uso de una cadena de formato similar a printfo scanfcon especificadores incrustados que indican tipos de argumentos.
  • Un valor centinela al final de los argumentos variadic.
  • Un argumento de recuento que indica el número de argumentos variados.

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), tampoco existe una forma confiable y genérica de reenviar el argumentos sin nombre en 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 existe una forma portátil de pasar el número de argumentos determinado dinámicamente a la llamada variada interna, como el número y el tamaño de los argumentos pasados ​​a tales llamadas generalmente deben conocerse en tiempo de compilación. Hasta cierto punto, esta restricción se puede relajar empleando macros variadicen lugar de funciones variadas. Además, la mayoría de los procedimientos de biblioteca estándar proporcionan vversiones alternativas prefijadas 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 un en va_listlugar de la lista de argumentos sin nombre real. Por lo tanto, una función variada definida por el usuario puede inicializar una va_listvariable utilizando 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 hay una forma confiable de pasar listas de argumentos sin nombre por valor en C, proporcionando API variadicfunciones sin proporcionar también funciones equivalentes, aceptarlas en su va_listlugar 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 adecuado 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 espera la función, o convertirlos al tipo requerido. Por lo tanto, se debe tener cuidado para garantizar la corrección a este respecto, 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 aplicadas a los argumentos sin nombre. Afloatse promoverá automáticamente a double. Del mismo modo, los argumentos de tipos más estrechos que an intserán promovidos 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)

Los atributos especifica el formato que una función toma printf, scanf, strftimeo strfmonargumentos de estilo que debe ser de tipo cotejan con una cadena de formato. Por ejemplo, la declaración:

extern  int my_printf  ( void  * my_object ,  const  char  * my_format ,  ...)  __attribute__  (( formato  ( printf ,  2 ,  3 )));

hace que el compilador verifique los argumentos en las llamadas a my_printfpara verificar su coherencia con el printfargumento de cadena de formato de estilo 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

#include  <stdio.h>#include  <stdarg.h>/ * imprime todos los argumentos uno a la vez hasta que se ve 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 ( vacío ) {  printargs ( 5 ,  2 ,  14 ,  84 ,  97 ,  15 ,  -1 ,  48 ,  -1 );  printargs ( 84 ,  51 ,  -1 ,  3 );  printargs ( -1 );  printargs ( 1 ,  -1 );  return  0 ; }

Este programa produce la salida:

5 2 14 84 97 15
84 51
1

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

void  MyPrintf ( const  char  * formato ,  ...) {  va_list  args ;  búfer char  [ BUFSIZ ]; va_start ( args ,  formato );  vsnprintf ( tampón ,  sizeof  tampón ,  formato ,  args );  va_end ( args );  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 forma parte de ISO C ni de POSIX. El archivo, 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 estilo nuevo 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, uno escribiría en su lugar:

#include  <stdio.h>#include  <varargs.h>/ * No hay ningún tipo "vacío"; 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 );  para  ( i  =  arg1 ;  i  > =  0 ;  i  =  va_arg ( ap ,  int ))  printf ( "% d" ,  i );  va_end ( ap );  putchar ( '\ n' );  volver ; }

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. [2] Por el contrario, no es posible mezclar definiciones de funciones antiguas con stdarg.h.

Referencias

  1. ^ "IEEE Std 1003.1 " . Consultado el 4 de julio de 2009 .stdarg.h
  2. ^ "Especificación UNIX única " . Consultado el 1 de agosto de 2007 .varargs.h
Obtenido de " https://en.wikipedia.org/w/index.php?title=Stdarg.h&oldid=1016263744#stdarg.h_macros "