Stdarg.h

Last updated

stdarg.h is a header in the C standard library of the C programming language that allows functions to accept an indefinite number of arguments. [1] It provides facilities for stepping through a list of function arguments of unknown number and type. C++ provides this functionality in the header cstdarg.

Contents

The contents of stdarg.h are typically used in variadic functions, though they may be used in other functions (for example, vprintf ) called by variadic functions.

Declaring variadic functions

Variadic functions are functions which may take a variable number of arguments and are declared with an ellipsis in place of the last parameter. An example of such a function is printf . A typical declaration is

intcheck(inta,doubleb,...);

Variadic functions must have at least one named parameter, so, for instance,

char*wrong(...);

is not allowed in C17 and earlier. (In C++ and C23, [2] such a declaration is permitted.) In C, a comma must precede the ellipsis if a named parameter is specified; in C++, it is optional.

Defining variadic functions

The same syntax is used in a definition:

longfunc(char,double,int,...);longfunc(chara,doubleb,intc,...){/* ... */}

An ellipsis may not appear in old-style function definitions.

stdarg.h types

NameDescriptionCompatibility
va_list type for iterating arguments C89

stdarg.h macros

NameDescriptioncompatibility
va_start Start iterating arguments with a va_listC89
va_arg Retrieve an argumentC89
va_end Free a va_listC89
va_copy Copy contents of one va_list to another C99

Accessing the arguments

To access the unnamed arguments, one must declare a variable of type va_list in the variadic function. The macro va_start is then called with two arguments: the first is the variable declared of the type va_list, the second is the name of the last named parameter of the function. In C23 the second argument will be optional and will not be evaluated. [2] After this, each invocation of the va_arg macro yields the next argument. The first argument to va_arg is the va_list and the second is the type of the next argument passed to the function. Finally, the va_end macro must be called on the va_list before the function returns. (It is not required to read in all the arguments.)

C99 provides an additional macro, va_copy, which can duplicate the state of a va_list. The macro invocation va_copy(va2, va1) copies va1 into va2.

There is no defined method for counting or classifying the unnamed arguments passed to the function. The function is simply required to know or determine this somehow, the means of which vary. Common conventions include:

Passing unnamed arguments to other calls

Because the size of the unnamed argument list is generally unknown (the calling conventions employed by most compilers do not permit determining the size of the unnamed argument block pointed at by va_list inside the receiving function), there is also no reliable, generic way to forward the unnamed arguments into another variadic function. Even where determining the size of the argument list is possible by indirect means (for example, by parsing the format string of fprintf()), there is no portable way to pass the dynamically determined number of arguments into the inner variadic call, as the number and size of arguments passed into such calls must generally be known at compile time. To some extent, this restriction can be relaxed by employing variadic macros instead of variadic functions. Additionally, most standard library procedures provide v-prefixed alternative versions which accept a reference to the unnamed argument list (i.e. an initialized va_list variable) instead of the unnamed argument list itself. For example, vfprintf() is an alternate version of fprintf() expecting a va_list instead of the actual unnamed argument list. A user-defined variadic function can therefore initialize a va_list variable using va_start and pass it to an appropriate standard library function, in effect passing the unnamed argument list by reference instead of doing it by value. Because there is no reliable way to pass unnamed argument lists by value in C, providing variadic API functions without also providing equivalent functions accepting va_list instead is considered a bad programming practice.

Type safety

Some C implementations provide C extensions that allow the compiler to check for the proper use of format strings and sentinels. Barring these extensions, the compiler usually cannot check whether the unnamed arguments passed are of the type the function expects, or convert them to the required type. Therefore, care should be taken to ensure correctness in this regard, since undefined behavior results if the types do not match. For example, if the expected type is int *, then a null pointer should be passed as (int *)NULL. Writing just NULL would result in an argument of type either int or void *, neither of which is correct. Another consideration is the default argument promotions applied to the unnamed arguments. A float will automatically be promoted to a double. Likewise, arguments of types narrower than an int will be promoted to int or unsigned int. The function receiving the unnamed arguments must expect the promoted type.

GCC has an extension that checks the passed arguments:

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

The format attribute specifies that a function takes printf, scanf, strftime or strfmon style arguments which should be type-checked against a format string. For example, the declaration:

externintmy_printf(void*my_object,constchar*my_format,...)__attribute__((format(printf,2,3)));

causes the compiler to check the arguments in calls to my_printf for consistency with the printf style format string argument my_format.

"5.27 Extensions to the C Language Family - Declaring Attributes of Functions" . Retrieved 2009-01-03.

Example

#include<stdio.h>#include<stdarg.h>/* print all args one at a time until a negative argument is seen;   all args are assumed to be of int type */voidprintargs(intarg1,...){va_listap;inti;va_start(ap,arg1);for(i=arg1;i>=0;i=va_arg(ap,int))printf("%d ",i);va_end(ap);putchar('\n');}intmain(void){printargs(5,2,14,84,97,15,-1,48,-1);printargs(84,51,-1,3);printargs(-1);printargs(1,-1);return0;}

This program yields the output:

5 2 14 84 97 15 84 51  1 

To call other var args functions from within your function (such as sprintf) you need to use the var arg version of the function (vsprintf in this example):

voidMyPrintf(constchar*format,...){va_listargs;charbuffer[BUFSIZ];va_start(args,format);vsnprintf(buffer,sizeofbuffer,format,args);va_end(args);FlushFunnyStream(buffer);}

varargs.h

Outdated versions of POSIX defined the legacy header varargs.h, which dates from before the standardization of C and provides functionality similar to stdarg.h. This header is part of neither ISO C nor POSIX. The file, as defined in the second version of the Single UNIX Specification, simply contains all of the functionality of C89 stdarg.h, with the exceptions that:

The interface is also different. For printargs example, one would instead write:

#include<stdio.h>#include<varargs.h>/* There is no "void" type; use an implicit int return. */printargs(arg1,va_alist)va_dcl/* no semicolon here! */{va_listap;inti;va_start(ap);/* only the va_list is given! */for(i=arg1;i>=0;i=va_arg(ap,int))printf("%d ",i);va_end(ap);putchar('\n');return;}

and is called the same way.

varargs.h requires old-style function definitions because of the way the implementation works. [3] Conversely, it is not possible to mix old-style function definitions with stdarg.h.

Related Research Articles

Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types. This allows a function or class declaration to reference via a generic variable another different class without creating full declaration for each of these different classes.

The C preprocessor is the macro preprocessor for several computer programming languages, such as C, Objective-C, C++, and a variety of Fortran languages. The preprocessor provides inclusion of header files, macro expansions, conditional compilation, and line control.

In computer science, a type signature or type annotation defines the inputs and outputs for a function, subroutine or method. A type signature includes the number, types, and order of the arguments required by a function. A type signature is typically used during overload resolution for choosing the correct definition of a function to be called among many overloaded forms.

<span class="mw-page-title-main">C syntax</span> Set of rules defining correctly structured programs

The syntax of the C programming language is the set of rules governing writing of software in C. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction. C was the first widely successful high-level language for portable operating-system development.

A variadic macro is a feature of some computer programming languages, especially the C preprocessor, whereby a macro may be declared to accept a varying number of arguments.

In mathematics and in computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments. Support for variadic functions differs widely among programming languages.

The computer programming languages C and Pascal have similar times of origin, influences, and purposes. Both were used to design their own compilers early in their lifetimes. The original Pascal definition appeared in 1969 and a first compiler in 1970. The first version of C appeared in 1972.

<span class="mw-page-title-main">C data types</span> Data types supported by the C programming language

In the C programming language, data types constitute the semantics and characteristics of storage of data elements. They are expressed in the language syntax in form of declarations for memory locations or variables. Data types also determine the types of operations or methods of processing of data elements.

A scanf format string is a control parameter used in various functions to specify the layout of an input string. The functions can then divide the string and translate into values of appropriate data types. String scanning functions are often supplied in standard libraries. Scanf is a function that reads formatted data from the standard input string, which is usually the keyboard and writes the results whenever called in the specified arguments.

sizeof is a unary operator in the programming languages C and C++. It generates the storage size of an expression or a data type, measured in the number of char-sized units. Consequently, the construct sizeof (char) is guaranteed to be 1. The actual number of bits of type char is specified by the preprocessor macro CHAR_BIT, defined in the standard include file limits.h. On most modern computing platforms this is eight bits. The result of sizeof has an unsigned integer type that is usually denoted by size_t.

The C and C++ programming languages are closely related but have many significant differences. C++ began as a fork of an early, pre-standardized C, and was designed to be mostly source-and-link compatible with C compilers of the time. Due to this, development tools for the two languages are often integrated into a single product, with the programmer able to specify C or C++ as their source language.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

In computing, compile-time function execution is the ability of a compiler, that would normally compile a function to machine code and execute it at run time, to execute the function at compile time. This is possible if the arguments to the function are known at compile time, and the function does not make any reference to or attempt to modify any global state.

In computer programming, variadic templates are templates that take a variable number of arguments.

Different command-line argument parsing methods are used by different programming languages to parse command-line arguments.

OpenHMPP - programming standard for heterogeneous computing. Based on a set of compiler directives, standard is a programming model designed to handle hardware accelerators without the complexity associated with GPU programming. This approach based on directives has been implemented because they enable a loose relationship between an application code and the use of a hardware accelerator (HWA).

In computer programming, ellipsis notation is used to denote ranges, an unspecified number of arguments, or a parent directory. Most programming languages require the ellipsis to be written as a series of periods; a single (Unicode) ellipsis character cannot be used.

X macros are an idiomatic usage of programming language macros for generating list-like structures of data or code. They are most useful when at least some of the lists cannot be composed by indexing, such as compile time. They provide reliable maintenance of parallel lists whose corresponding items must be declared or executed in the same order.

<span class="mw-page-title-main">LFE (programming language)</span>

Lisp Flavored Erlang (LFE) is a functional, concurrent, garbage collected, general-purpose programming language and Lisp dialect built on Core Erlang and the Erlang virtual machine (BEAM). LFE builds on Erlang to provide a Lisp syntax for writing distributed, fault-tolerant, soft real-time, non-stop applications. LFE also extends Erlang to support metaprogramming with Lisp macros and an improved developer experience with a feature-rich read–eval–print loop (REPL). LFE is actively supported on all recent releases of Erlang; the oldest version of Erlang supported is R14.

C23 is the informal name for what will likely become ISO/IEC 9899:2024, the next standard for the C programming language, which will replace C17. It was started in 2016 informally as C2x, and expected to be published in 2024. The most recent publicly available working draft of C23 was released on April 1, 2023. The first WG14 meeting for the C2x draft was held in October 2019, virtual remote meetings were held in 2020 due to the COVID-19 pandemic, then various teleconference meetings continued to occur through 2023.

References

  1. "IEEE Std 1003.1 stdarg.h" . Retrieved 2009-07-04.
  2. 1 2 Gilding, Alex; Meneide, JeanHeyd (2022-04-15). "WG14-N2975 : Relax requirements for variadic parameter lists, v3" (PDF).
  3. "Single UNIX Specification varargs.h" . Retrieved 2007-08-01.