stringtranslate.com

estándar.h

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.

Creació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 una función de este tipo es printf. Respectivamente, las declaraciones y definiciones se realizan de manera similar.

int comprobar ( int a , doble b , ...);     int comprobar ( int a , doble b , ...){ //... }      

Según el estándar, las funciones varádicas sin parámetros nombrados no están permitidas 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.

Algunas declaraciones de funciones de estilo C de K&R no utilizan puntos suspensivos. [3]

Tipos de stdarg.h

macros stdarg.h

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:

Pasar argumentos sin nombre a otras llamadas

Como el tamaño de la lista de argumentos sin nombre generalmente es desconocido, 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 normalmente no puede verificar si los argumentos sin nombre que se pasan 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 just 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. [ cita requerida ]

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 para my_printfverificar la coherencia con el printfformato de estilo del argumento de cadena my_format[4]

Ejemplo

#incluir <stdio.h> #incluir <stdarg.h>  /*Obtener la suma de las variables*/ void suma ( int count , ...) { va_list ap ; int i = 0 ; int suma = 0 ; va_start ( ap , arg1 ); for ( i = 0 ; i < count ; i ++ ) suma += va_arg ( ap , int ); va_end ( ap ); return suma ; }                               int main ( void ) { printf ( "%i" , suma ( 2 , 1 , 3 )); devolver 0 ; }       

Este programa debería obtener el siguiente resultado:

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 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:

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. [5] 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. ^ de Gilding, Alex; Meneide, JeanHeyd (15 de abril de 2022). "WG14-N2975: Relajar requisitos para listas de parámetros variádicos, v3" (PDF) .
  3. ^ "Definiciones de funciones de estilo antiguo". Lenguaje C de GNU . 2007. Consultado el 15 de noviembre de 2024 .
  4. ^ "5.27 Extensiones de la familia de lenguajes C - Declaración de atributos de funciones" . Consultado el 3 de enero de 2009 .
  5. ^ "Especificación única de UNIX varargs.h" . Consultado el 1 de agosto de 2007 .