Scrigroup - Documente si articole


HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows

AspAutocadCDot netExcelFox proHtmlJava
LinuxMathcadPhotoshopPhpSqlVisual studioWindowsXml

Libraries - Mathematical functions, Variable numbers of arguments


+ Font mai mare | - Font mai mic


  • 1. Introduction
  • 2. Diagnostics
  • 3. Character handling
  • 4. Localization
  • 5. Limits
  • 6. Mathematical functions
  • 7. Non-local jumps
  • 8. Signal handling
  • Variable numbers of arguments
  • 10. Input and output
  • 11. Formatted I/O
  • 12. Character I/O
  • 13. Unformatted I/O
  • 14. Random access functions
  • 15. General Utilities
  • 16. String handling
  • 17. Date and time
  • 18. Summary

1. Introduction

There is no doubt that the Standard Committee's decision to define a set of library routines will prove to be a huge benefit to users of C. Previously there were no standard, accepted, definitions of library routines to provide support for the language. As a result, portability suffered seriously.

The library routines do not have to be present; they will only be present in a hosted environment-typically the case for applications programmers. Writers of embedded systems and the writers of the hosted environment libraries will not have the libraries present. They are using 'raw' C, in a freestanding environment, and this chapter will not be of much interest to them.

The descriptions (except for this introduction) are not meant to be read as a whole chapter, but as individual pieces. The material included here is meant more for information and convenient reference than as a full tutorial introduction. It would take a full book by itself to do real justice to the libraries.

1.1. Headers and standard types

A number of types and macros are used widely by the library functions. Where necessary, they are defined in the appropriate #include file for that function. The header will also declare appropriate types and prototypes for the library functions. Some important points should be noted here:

  • All external identifiers and macro names declared in any of the library headers are reserved. They must not be used, or redefined, for any other purpose. In some cases they may be 'magic'-their names may be known to the compiler and cause it to use special methods to implement them.
  • All identifiers that begin with an underscore are reserved.
  • Headers may be included in any order, and more than once, but must be included outside of any external declaration or definition and before any use of the functions or macros defined inside them.
  • Giving a 'bad value' to a function-say a null pointer, or a value outside the range of values expected by the function-results in undefined behaviour unless otherwise stated.

The Standard isn't quite as restrictive about identifiers as the list above is, but it's a brave move to make use of the loopholes. Play safe instead.

The Standard headers are:

<assert.h> <locale.h> <stddef.h>
<ctype.h> <math.h> <stdio.h>
<errno.h> <setjmp.h> <stdlib.h>
<float.h> <signal.h> <string.h>
<limits.h> <stdarg.h> <time.h>

A last general point is that many of the library routines may be implemented as macros, provided that there will be no problems to do with side-effects (as Chapter 7 describes). The Standard guarantees that, if a function is normally implemented as a macro, there will also be a true function provided to do the same job. To use the real function, either undefine the macro name with #undef, or enclose its name in parentheses, which ensures that it won't be treated as a macro:

some function('Might be a macron');
(some function)('Can't be a macron');

1.2. Character set and cultural dependencies

The Committee has introduced features that attempt to cater for the use of C in environments which are not based on the character set of US ASCII and where there are cultural dependencies such as the use of comma or full stop to indicate the decimal point. Facilities have been provided (see Section 4) for setting a program's idea of its locale, which is used to control the behaviour of the library functions.

Providing full support for different native languages and customs is a difficult and poorly understood task; the facilities provided by the C library are only a first step on the road to a full solution.

In several places the 'C locale' is referred to. This is the only locale defined by the Standard and effectively provides support for the way that Old C worked. Other locale settings may provide different behaviour in implementation-defined ways.

1.3. The <stddef.h> Header

There are a small number of types and macros, found in <stddef.h>, which are widely used in other headers. They are described in the following paragraphs.

Subtracting one pointer from another gives a result whose type differs between different implementations. To allow safe use of the difference, the type is defined in <stddef.h> to be ptrdiff_t. Similarly, you can use size_t to store the result of sizeof.

For reasons which still escape us, there is an 'implementation defined null pointer constant' defined in <stddef.h> called NULL. Since the language explicitly defines the integer constant to be the value which can be assigned to, and compared with, a null pointer, this would seem to be unnecessary. However, it is very common practice among experienced C programmers to write this sort of thing:

#include <stdio.h>
#include <stddef.h>
FILE *fp;

if((fp = fopen('somefile', 'r')) != NULL)s_tr;

distance = offsetof(s_tr, c);
printf('Offset of x.c is %lu bytesn',
(unsigned long)distance);


Example 1

The expression s_tr.c must be capable of evaluation as an address constant (see Chapter  . If the member whose offset you want is a bitfield, then you're out of luck; offsetof has undefined behaviour in that case.

Note carefully the way that a size_t has to be cast to the longest possible unsigned type to ensure that not only is the argument to printf of the type that it expects (%luis the format string for unsigned long), but also no precision is lost. This is all because the type of size_t is not known to the programmer.

The last item declared in <stddef.h> is wchar_t, an integral type large enough to hold a wide character from any supported extended character sets.

1.4. The <errno.h> Header

This header defines errno along with the macros EDOM and ERANGE, which expand to nonzero integral constant expressions; their form is additionally guaranteed to be acceptable to #if directives. The latter two are used by the mathematical functions to report which kind of errors they encountered and are more fully described later.

errno is provided to tell you when library functions have detected an error. It is not necessarily, as it used to be, an external variable, but is now a modifiable lvalue that has type int. It is set to zero at program start-up, but from then on never reset unless explicitly assigned to; in particular, the library routines never reset it. If an error occurs in a library routine, errno is set to a particular value to indicate what went wrong, and the routine returns a value (often −1) to indicate that it failed. The usual use is like this:

#include <stdio.h>
#include <stddef.h>
#include <errno.h>

errno = 0;
if(some_library_function(arguments) < 0)

Example 2

Note that assert returns no value.

3. Character handling

There are a variety of functions provided for testing and mapping characters. The testing functions, which are described first, allow you to test if a character is of a particular type, such as alphabetic, upper or lower case, numeric, a control character, a punctuation mark, printable or not and so on. The character testing functions return an integer, either zero if the character supplied is not of the category specified, or non-zero if it was. The functions all take an integer argument, which should either be an int, the value of which should be representable as unsigned char, or the integer constant EOF, as returned from functions such as getchar(). The behaviour is undefined if it is not.

These functions depend on the program's locale setting.

A printing character is a member of an implementation defined character set. Each printing character occupies one printing position. A control character is a member of an implementation defined character set, each of which is not a printing character. If the 7-bit ASCII character set is used, the printing characters are those that lie between space (0x20) and tilde (0x7e), the control characters are those between NUL (0x0) and US (0x1f), and the character DEL (0x7f).

The following is a summary of all the character testing functions. The header <ctype.h> must be included before any of them is used.

isalnum(int c)

True if c is alphabetic or a digit; specifically (isalpha(c)||isdigit(c)).

isalpha(int c)

True if (isupper(c)||islower(c)).

Also true for an implementation-defined set of characters which do not return true results from any of iscntrl, isdigit, ispunct or isspace. In the C locale, this extra set of characters is empty.

iscntrl(int c)

True if c is a control character.

isdigit(int c)

True if c is a decimal digit.

isgraph(int c)

True if c is any printing character except space.

islower(int c)

True if c is a lower case alphabetic letter. Also true for an implementation defined set of characters which do not return true results from any of iscntrl, isdigit, ispunct or isspace. In the C locale, this extra set of characters is empty.

isprint(int c)

True if c is a printing character (including space).

ispunct(int c)

True if c is any printing character that is neither a space nor a character which would return true from isalnum.

isspace(int c)

True if c is either a white space character (one of ' ' 'f' 'n' 'r' 't' 'v') or, in other than the C locale, characters which would not return true from isalnum

isupper(int c)

True if c is an upper case alphabetic character.

Also true for an implementation-defined set of characters which do not return true results from any of iscntrl, isdigit, ispunct or isspace. In the C locale, this extra set of characters is empty.

isxdigit(int c)

True if c is a valid hexadecimal digit.

Two additional functions map characters from one set into another. The function tolower will, if given a upper case character as its argument, return the lower case equivalent. For example,

tolower('A') == 'a'

If tolower is given any character other than an upper case letter, it will return that character.

The converse function toupper maps lower case alphabetic letters onto their upper case equivalent.

For each, the conversion is only performed if there is a corresponding character in the alternate case. In some locales, not all upper case characters have lower case equivalents, and vice versa.

4. Localization

This is where the program's idea of its current locale can be controlled. The header file <locale.h> declares the setlocale and localeconv functions and a number of macros:


all of which expand to integral constant expressions and are used as values of the category argument to setlocale (other names may also be defined: they will all start with LC_X where X is an upper case letter), and the type

struct lconv

which is used for storing information about the formatting of numeric values. For members of type char, CHAR_MAX is used to indicate that the value is not available in the current locale.

lconv contains at least the following members:

char *decimal_point

The character used for the decimal point in formatted non-monetary values. in the C locale.

char *thousands_sep

The character used for separating groups of digits to the left of the decimal point in formatted non-monetary values. in the C locale.

char *grouping

Defines the number of digits in each group when formatting non-monetary values. The elements are interpreted as follows: A value of CHAR_MAX indicates that no further grouping is to be performed; indicates that the previous element should be repeated for the remaining digits; if any other character is used, its integer value represents the number of digits that comprise the current group (the next character in the sequence is interpreted before grouping). in the C locale. As an example, specifies that digits should be grouped in threes; the terminating null in the string signifies that the repeats.

char *int_curr_symbol

The first three characters are used to hold the alphabetic international currency symbol for the current locale, the fourth character is used to separate the international currency symbol from the monetary quantity. in the C locale.

char *currency_symbol

The currency symbol for the current locale. in the C locale.

char *mon_decimal_point

The character used as the decimal point when formatting monetary values. in the C locale.

char *mon_thousands_sep

The digit group separator for formatted monetary values. in the C locale.

char *mon_grouping

Defines the number of digits in each group when formatting monetary values. Its elements are interpreted as those for grouping. in the C locale.

char *positive_sign

The string used to signify a non-negative monetary value. in the C locale.

char *negative_sign

The string used to signify a negative monetary value. in the C locale.

char int_frac_digits

The number of digits to be displayed after the decimal point in an internationally formatted monetary value. CHAR_MAX in the C locale.

char frac_digits

The number of digits to be displayed after the decimal point in a non-internationally formatted monetary value. CHAR_MAX in the C locale.

char p_cs_precedes

A value of indicates that the currency_symbol should precede the value when formatting a non-negative monetary quantity; a value of indicates that it should follow. CHAR_MAX in the C locale.

char p_sep_by_space

A value of 1 indicates that the currency symbol is separated by a space from the value when formatting a non-negative monetary quantity; 0 indicates no space. CHAR_MAX in the C locale.

char n_cs_precedes

As p_cs_precedes for negative monetary values. CHAR_MAX in the C locale.

char n_sep_by_space

As p_sep_by_space for negative monetary values. CHAR_MAX in the C locale.

char p_sign_posn

Indicates the position of the positive_sign for a non-negative formatted monetary value according to the following:

parentheses surround quantity and currency_symbol

the string precedes the quantity and currency_symbol

the string follows the quantity and currency_symbol

the string precedes the currency_symbol

the string follows the currency_symbol

CHAR_MAX in the C locale.

char n_sign_posn

As p_sign_posn for negative monetary values. CHAR_MAX in the C locale.

4.1. The setlocale function

#include <locale.h>

char *setlocale(int category, const char *locale);

This function allows the program's idea of its locale to be set. All or parts of the locale can be set by providing values for category as follows:


Set entire locale.


Modify behaviour of strcoll and strxfrm.


Modify behaviour of character-handling functions.


Modify monetary formatting information returned by localeconv.


Modify decimal-point character for formatted I/O and string conversion routines.


Modify behaviour of strftime.

The values for locale can be:


Select the minimal environment for C translation

Select the implementation-defined 'native environment'

implementation defined

Select other environments

When the program starts, it has an environment as if

setlocale(LC_ALL, 'C');

has been executed.

The current string associated with a given category can be queried by passing a null pointer as the value for locale; if the selection can be performed, the string associated with the specified category for the new locale is returned. This string is such that if it is used in a subsequent call to setlocale, along with its associated category, that part of the program's locale will be restored. If the selection cannot be performed, a null pointer is returned and the locale is not changed.

4.2. The localeconv function

#include <locale.h>

struct lconv *localeconv(void);

The function returns a pointer to a structure of type struct lconv, set according to the current locale, which may be overwritten by subsequent calls to localeconv or setlocale. The structure must not be modified in any other way.

For example, if in the current locale monetary values should be represented as


positive format


negative format

IRP 1,234.56

international format

then the monetary members of lconv would have the values:


'IRP '

















5. Limits

Two header files <float.h> and <limits.h> define several implementation specific limits.

5.1. Limits.h

Table 1 gives the names declared, the allowable values, and a comment on what they mean. For example, the description of SHRT_MIN shows that in a given implementation the value must be less than or equal to −32767: this means that for maximum portability a program cannot rely on short variables being able to hold values more negative than −32767. Implementations may choose to support values which are more negative but must provide support for at least −32767.


Allowable value




bits in a char


see note

max value of a char


see note

min value of a char



max value of an int



min value of an int



max value of a long



min value of a long



max number of bytes in a multibyte character



max value of a signed char



min value of a signed char



max value of a short



min value of a short



max value of an unsigned char



max value of an unsigned int



max value of an unsigned long



max value of an unsigned short

Note: if the implementation treats chars as signed, then the values of CHAR_MAX and CHAR_MIN are the same as the equivalent SCHAR versions. If not, then the value of CHAR_MIN is zero and the value of CHAR_MAX is equal to the value of UCHAR_MAX.

Table 1. <limits.h>

5.2. Float.h

For floating point numbers, the file <float.h> contains a similar set of minimum values. (It is assumed that where no minimum value is specified, there is either no minimum, or the value depends on another value.)


Allowable value




the radix of exponent representation



the number of digits of precision in a double



minimum positive number such that 1.0 + x ≠ 1.0



the number of base FLT_RADIX digits in the mantissa part of a double



max value of a double



max value of exponent (base 10) of a double



max value of exponent (base FLT_RADIX)) of a double



min value of a double



minimum value of exponent (base 10) of a double



min value of exponent part of a double (base FLT_RADIX)



the number of digits of precision in a float



minimum positive number such that 1.0 + x ≠ 1.0



the number of base FLT_RADIX digits in the mantissa of a float



max value of a float



max value (base 10) of exponent part of a float



max value (base FLT_RADIX) of exponent part of a float



min value of a float



min value (base 10) of exponent part of a float



min value (base FLT_RADIX) of exponent part of a float



affects rounding of floating point addition:




towards zero


to nearest


towards +infinity


towards -infinity

any other value is implementation defined.



the number of digits of precision in a long double



minimum positive number such that 1.0 + x ≠= 1.0



the number of base FLT_RADIX digits in the mantissa part of a long double



max value of a long double



max value of exponent (base 10) of a long double



max value of exponent (base FLT_RADIX) of a long double



minimum value of a long double



min value of exponent part (base 10) of a long double



min value of exponent part of a long double (base FLT_RADIX)

Table 2. <float.h>

6. Mathematical functions

If you are writing mathematical programs, involving floating point calculations and so on, then you will undoubtedly require access to the mathematics library. This set of functions all take double arguments, and return a double result. The functions and associated macros are defined in the include file <math.h>.

The macro HUGE_VAL is defined, which expands to a positive double expression, which is not necessarily representable as a float.

For all the functions, a domain error occurs if an input argument is outside the domain over which the function is defined. An example might be attempting to take the square root of a negative number. If this occurs, errno is set to the constant EDOM, and the function returns an implementation defined value.

If the result of the function cannot be represented as a double value then a range error occurs. If the magnitude of the result is too large, the functions return HUGE_VAL (the sign will be correct) and errno is set to ERANGE. If the result is too small, is returned and the value of errno is implementation defined.

The following list briefly describes each of the functions available:

double acos(double x);

Principal value of the arc cosine of x in the range 0-π radians.
Errors: EDOM if x is not in the range −1-1.

double asin(double x);

Principal value of the arc sine of x in the range -π/2-+π/2 radians.
Errors: EDOM if x is not in the range .

double atan(double x);

Principal value of the arc tangent of x in the range -π/2-+π/2 radians.

double atan2(double y, double x);

Principal value of the arc tangent of y/x in the range -π-+π radians, using the signs of both arguments to determine the quadrant of the return value.
Errors: EDOM may occur if both x and y are zero.

double cos(double x);

Cosine of x (x measured in radians).

double sin(double x);

Sine of x (x measured in radians).

double tan(double x);

Tangent of x (x measured in radians). When a range error occurs, the sign of the resulting HUGE_VAL is not guaranteed to be correct.

double cosh(double x);

Hyperbolic cosine of x
Errors: ERANGE occurs if the magnitude of x is too large.

double sinh(double x);

Hyperbolic sine of x
Errors: ERANGE occurs if the magnitude of x is too large.

double tanh(double x);

Hyperbolic tangent of x.

double exp(double x);

Exponential function of x. Errors: ERANGE occurs if the magnitude of x is too large.

double frexp(double value, int *exp);

Break a floating point number into a normalized fraction and an integral power of two. This integer is stored in the object pointed to by exp.

double ldexp(double x, int exp);

Multiply x by 2 to the power exp
Errors: ERANGE may occur.

double log(double x);

Natural logarithm of x
Errors: EDOM occurs if x is negative. ERANGE may occur if x is zero.

double log10(double x);

Base-ten logarithm of x
Errors: EDOM occurs if x is negative. ERANGE may occur if x is zero.

double modf(double value, double *iptr);

Break the argument value into integral and fractional parts, each of which has the same sign as the argument. It stores the integrbal part as a double in the object pointed to by iptr, and returns the fractional part.

double pow(double x, double y);

Compute x to the power y
Errors: EDOM occurs if x < 0 and y not integral, or if the result cannot be represented if x is 0, and y ≤ 0. ERANGE may also occur.

double sqrt(double x);

Compute the square root of x
Errors: EDOM occurs if x is negative.

double ceil(double x);

Smallest integer not less than x.

double fabs(double x);

Absolute value of x.

double floor(double x);

Largest integer not greater than x.

double fmod(double x, double y);

Floating point remainder of x/y
Errors: If y is zero, it is implementation defined whether fmod returns zero or a domain error occurs.

7. Non-local jumps

Provision is made for you to perform what is, in effect, a goto from one function to another. It isn't possible to do this by means of a goto and a label, since labels have only function scope. However, the macro setjmp and function longjmp provide an alternative, known as a non-local goto, or a non-local jump.

The file <setjmp.h> declares something called a jmp_buf, which is used by the cooperating macro and function to store the information necessary to make the jump. The declarations are as follows:

#include <setjmp.h>

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);

The setjmp macro is used to initialise the jmp_buf and returns zero on its initial call. The bizarre thing is that it returns again, later, with a non-zero value, when the corresponding longjmp call is made! The non-zero value is whatever value was supplied to the call of longjmp. This is best explained by way of an example:

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

void func(void);
jmp_buf place;


* This call will never return - it
* 'jumps' back above.
printf('What! func returned!n');


Example 3

The val argument to longjmp is the value seen in the second and subsequent 'returns' from setjmp. It should normally be something other than 0; if you attempt to return 0 via longjmp, it will be changed to 1. It is therefore possible to tell whether the setjmp was called directly, or whether it was reached by calling longjmp.

If there has been no call to setjmp before calling longjmp, the effect of longjmp is undefined, almost certainly causing the program to crash. The longjmp function is never expected to return, in the normal sense, to the instructions immediately following the call. All accessible objects on 'return' from setjmp have the values that they had when longjmp was called, except for objects of automatic storage class that do not have volatile type; if they have been changed between the setjmp and longjmp calls, their values are indeterminate.

The longjmp function executes correctly in the contexts of interrupts, signals and any of their associated functions. If longjmp is invoked from a function called as a result of a signal arriving while handling another signal, the behaviour is undefined.

It's a serious error to longjmp to a function which is no longer active (i.e. it has already returned or another longjump call has transferred to a setjmp occurring earlier in a set of nested calls).

The Standard insists that, apart from appearing as the only expression in an expression statement, setjmp may only be used as the entire controlling expression in an if, switch, do, while, or for statement. A slight extension to that rule is that as long as it is the whole controlling expression (as above) the setjmp call may be the subject of the ! operator, or may be directly compared with an integral constant expression using one of the relational or equality operators. No more complex expressions may be employed. Examples are:

setjmp(place); /* expression statement */
if(setjmp(place)) /* whole controlling expression */
if(!setjmp(place)) /* whole controlling expression */
if(setjmp(place) < 4) /* whole controlling expression */
if(setjmp(place)<;4 && 1!=2) /* forbidden */

8. Signal handling

Two functions allow for asynchronous event handling to be provided. A signal is a condition that may be reported during program execution, and can be ignored, handled specially, or, as is the default, used to terminate the program. One function sends signals, another is used to determine how a signal will be processed. Many of the signals may be generated by the underlying hardware or operating system as well as by means of the signal-sending function raise.

The signals are defined in the include file <signal.h>.


Abnormal termination, such as instigated by the abort function. (Abort.)


Erroneous arithmetic operation, such as divide by 0 or overflow. (Floating point exception.)


An 'invalid object program' has been detected. This usually means that there is an illegal instruction in the program. (Illegal instruction.)


Interactive attention signal; on interactive systems this is usually generated by typing some 'break-in' key at the terminal. (Interrupt.)


Invalid storage access; most frequently caused by attempting to store some value in an object pointed to by a bad pointer. (Segment violation.)


Termination request made to the program. (Terminate.)

Some implementations may have additional signals available, over and above this standard set. They will be given names that start SIG, and will have unique values, apart from the set above.

The function signal allows you to specify the action taken on receipt of a signal. Associated with each signal condition above, there is a pointer to a function provided to handle this signal. The signal function changes this pointer, and returns the original value. Thus the function is defined as

#include <signal.h>
void (*signal (int sig, void (*func)(int)))(int);

That is to say, signal is a function that returns a pointer to another function. This second function takes a single int argument and returns void. The second argument to signal is similarly a pointer to a function returning void which takes an int argument.

Two special values may be used as the func argument (the signal-handling function), SIG_DFL, the initial, default, signal handler; and SIG_IGN, which is used to ignore a signal. The implementation sets the state of all signals to one or other of these values at the start of the program.

If the call to signal succeeds, the previous value of func for the specified signal is returned. Otherwise, SIG_ERR is returned and errno is set.

When a signal event happens which is not being ignored, if the associated func is a pointer to a function, first the equivalent of signal(sig, SIG_DFL) is executed. This resets the signal handler to the default action, which is to terminate the program. If the signal was SIGILL then this resetting is implementation defined. Implementations may choose to 'block' further instances of the signal instead of doing the resetting.

Next, a call is made to the signal-handling function. If that function returns normally, then under most circumstances the program will resume at the point where the event occurred. However, if the value of sig was SIGFPE (a floating point exception), or any implementation defined computational exception, then the behaviour is undefined. The most usual thing to do in the handler for SIGFPE is to call one of the functions abort, exit, or longjmp.

The following program fragment shows the use of signal to perform a tidy exit to a program on receipt of the interrupt or 'interactive attention' signal.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

FILE *temp_file;
void leave(int sig);

/* can't get here */

* on receipt of SIGINT, close tmp file
* but beware - calling library functions from a
* signal handler is not guaranteed to work in all
* implementations..
* this is not a strictly conforming program

leave(int sig)

Example 4

It is possible for a program to send signals to itself by means of the raise function. This is defined as follows

include <signal.h>
int raise (int sig);

The signal sig is sent to the program.

Raise returns zero if successful, non-zero otherwise. The abort library function is essentially implementable as follows:

#include <signal.h>


If a signal occurs for any reason other than calling abort or raise, the signal-handling function may only call signal or assign a value to a volatile static object of type sig_atomic_t. The type sig_atomic_t is declared in <signal.h>. It is the only type of object that can safely be modified as an atomic entity, even in the presence of asynchronous interrupts. This is a very onerous restriction imposed by the Standard, which, for example, invalidates the leave function in the example program above; although the function would work correctly in some environments, it does not follow the strict rules of the Standard.

Variable numbers of arguments

It is often desirable to implement a function where the number of arguments is not known, or is not constant, when the function is written. Such a function is printf, described in Section 11 []. The following example shows the declaration of such a function.

int f(int, );

int f(int, )

int g()

Example 5

In order to access the arguments within the called function, the functions declared in the <stdarg.h> header file must be included. This introduces a new type, called a va_list, and three functions that operate on objects of this type, called va_start, va_arg, and va_end.

Before any attempt can be made to access a variable argument list, va_start must be called. It is defined as

#include <stdarg.h>
void vastart(valist ap, parmN);

The va_start macro initializes ap for subsequent use by the functions va_arg and va_end. The second argument to va_start, parmN is the identifier naming the rightmost parameter in the variable parameter list in the function definition (the one just before the , ). The identifier parmN must not be declared with register storage class or as a function or array type.

Once initialized, the arguments supplied can be accessed sequentially by means of the va arg macro. This is peculiar because the type returned is determined by an argument to the macro. Note that this is impossible to implement as a true function, only as a macro. It is defined as

#include <stdarg.h>
type va arg(va list ap, type);

Each call to this macro will extract the next argument from the argument list as a value of the specified type. The va_list argument must be the one initialized by va_start. If the next argument is not of the specified type, the behaviour is undefined. Take care here to avoid problems which could be caused by arithmetic conversions. Use of char or short as the second argument to va_arg is invariably an error: these types always promote up to one of signed int or unsigned int, and float converts to double. Note that it is implementation defined whether objects declared to have the types char, unsigned char, unsigned short and unsigned bitfields will promote to unsigned int, rather complicating the use of va_arg. This may be an area where some unexpected subtleties arise; only time will tell.

The behaviour is also undefined if va_arg is called when there were no further arguments.

The type argument must be a type name which can be converted into a pointer to such an object simply by appending a to it (this is so the macro can work). Simple types such as char are fine (because char * is a pointer to a character) but array of char won't work (char [] does not turn into 'pointer to array of char' by appending a ). Fortunately, arrays can easily be processed by remembering that an array name used as an actual argument to a function call is converted into a pointer. The correct type for an argument of type 'array of char' would be char *.

When all the arguments have been processed, the va_end function should be called. This will prevent the va_list supplied from being used any further. If va end is not used, the behaviour is undefined.

The entire argument list can be re-traversed by calling va_start again, after calling va_end. The va_end function is declared as

#include <stdarg.h>
void va_end(va list ap);

The following example shows the use of va_start, va_arg, and va_end to implement a function that returns the biggest of its integer arguments.

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>

int maxof(int, ) ;
void f(void);


int maxof(int n args, )

return max;

void f(void)

Example 6

10. Input and output

10.1. Introduction

One of the reasons that has prevented many programming languages from becoming widely used for 'real programming' is their poor support for I/O, a subject which has never seemed to excite language designers. C has avoided this problem, oddly enough, by having no I/O at all! The C language approach has always been to do I/O using library functions, which ensures that system designers can provide tailored I/O instead of being forced to change the language itself.

As C has evolved, a library package known as the 'Standard I/O Library' or stdio, has evolved with it and has proved to be both flexible and portable. This package has now become part of the Standard.

The old stdio package relied heavily on the UNIX model of file access, in particular the assumption that there is no distinction between unstructured binary files and files containing readable text. Many operating systems do maintain a distinction between the two, and to ensure that C programs can be written portably to run on both types of file model, the stdio package has been modified. There are changes in this area which affect many existing programs, although strenuous efforts were taken to limit the amount of damage.

Old C programs should still be able work unmodified in a UNIX environment.

10.2. The I/O model

The I/O model does not distinguish between the types of physical devices supporting the I/O. Each source or sink of data (file) is treated in the same way, and is viewed as a stream of bytes. Since the smallest object that can be represented in C is the character, access to a file is permitted at any character boundary. Any number of characters can be read or written from a movable point, known as the file position indicator. The characters will be read, or written, in sequence from this point, and the position indicator moved accordingly. The position indicator is initially set to the beginning of a file when it is opened, but can also be moved by means of positioning requests. (Where random access is not possible, the file position indicator is ignored.) Opening a file in append mode has an implementation defined effect on the stream's file position indicator.

The overall effect is to provide sequential reads or writes unless the stream was opened in append mode, or the file position indicator is explicitly moved.

There are two types of file, text files and binary files, which, within a program, are manipulated as text streams and binary streams once they have been opened for I/O. The stdio package does not permit operations on the contents of files 'directly', but only by viewing them as streams.

10.2.1. Text streams

The Standard specifies what is meant by the term text stream, which essentially considers a file to contain lines of text. A line is a sequence of zero or more characters terminated by a newline character. It is quite possible that the actual representation of lines in the external environment is different from this and there may be transformations of the data stream on the way in and out of the program; a common requirement is to translate the 'n' line-terminator into the sequence 'rn' on output, and do the reverse on input. Other translations may also be necessary.

Data read in from a text stream is guaranteed to compare equal to the data that was earlier written out to the file if the data consists only of complete lines of printable characters and the control characters horizontal-tab and newline, no newline character is immediately preceded by space characters and the last character is a newline.

It is guaranteed that, if the last character written to a text file is a newline, it will read back as the same.

It is implementation defined whether the last line written to a text file must terminate with a newline character; this is because on some implementations text files and binary files are the same.

Some implementations may strip the leading space from lines consisting only of a space followed by a newline, or strip trailing spaces at the end of a line!

An implementation must support text files with lines containing at least 254 characters, including the terminating newline.

Opening a text stream in update mode may result in a binary stream in some implementations.

Writing on a text stream may cause some implementations to truncate the file at that point-any data beyond the last byte of the current write being discarded.

10.2.2. Binary streams

A binary stream is a sequence of characters that can be used to record a program's internal data, such as the contents of structures or arrays in binary form. Data read in from a binary stream will always compare equal to data written out earlier to the same stream, under the same implementation. In some circumstances, an implementation-defined number of NUL characters may be appended to a binary stream.

The contents of binary files are exceedingly machine specific, and not, in general, portable.

10.2.3. Other streams

Other stream types may exist, but are implementation defined.

10.3. The stdio.h header file

To provide support for streams of the various kinds, a number of functions and macros exist. The <stdio.h> header file contains the various declarations necessary for the functions, together with the following macro and type declarations:


The type of an object used to contain stream control information. Users of stdio never need to know the contents of these objects, but simply manipulate pointers to them. It is not safe to copy these objects within the program; sometimes their addresses may be 'magic'.


A type of object that can be used to record unique values of a stream's file position indicator.


Values used to control the buffering of a stream in conjunction with the setvbuf function.


The size of the buffer used by the setbuf function. An integral constant expression whose value is at least 256.


A negative integral constant expression, indicating the end-of-file condition on a stream i.e. that there is no more input.


The maximum length which a filename can have, if there is a limit, or otherwise the recommended size of an array intended to hold a file name.


The minimum number of files that the implementation guarantees may be held open concurrently; at least eight are guaranteed. Note that three predefined streams exist and may need to be closed if a program needs to open more than five files explicitly.


The maximum length of the string generated by tmpnam; an integral constant expression.


Integral constant expressions used to control the actions of fseek.


The minimum number of unique filenames generated by tmpnam; an integral constant expression with a value of at least 25.

stdin stdout stderr

Predefined objects of type (FILE *) referring to the standard input, output and error streams respectively. These streams are automatically open when a program starts execution.

10.4. Opening, closing and buffering of streams

10.4.1. Opening

A stream is connected to a file by means of the fopen, freopen or tmpfile functions. These functions will, if successful, return a pointer to a FILE object.

Three streams are available without any special action; they are normally all connected to the physical device associated with the executing program: usually your terminal. They are referred to by the names stdin, the standard input, stdout, the standard output, and stderr, the standard error streams. Normal keyboard input is from stdin, normal terminal output is to stdout, and error messages are directed to stderr. The separation of error messages from normal output messages allows the stdout stream to be connected to something other than the terminal device, and still to have error messages appear on the screen in front of you, rather than to be redirected to this file. These files are only fully buffered if they do not refer to interactive devices.

As mentioned earlier, the file position indicator may or may not be movable, depending on the underlying device. It is not possible, for example, to move the file position indicator on stdin if that is connected to a terminal, as it usually is.

All non-temporary files must have a filename, which is a string. The rules for what constitutes valid filenames are implementation defined. Whether a file can be simultaneously open multiple times is also implementation defined. Opening a new file may involve creating the file. Creating an existing file causes its previous contents to be discarded.

10.4.2. Closing

Files are closed by explicitly calling fclose, exit or by returning from main. Any buffered data is flushed. If a program stops for some other reason, the status of files which it had open is undefined.

10.4.3. Buffering

There are three types of buffering:


Minimum internal storage is used by stdio in an attempt to send or receive data as soon as possible.

Line buffered

Characters are processed on a line-by-line basis. This is commonly used in interactive environments, and internal buffers are flushed only when full or when a newline is processed.

Fully buffered

Internal buffers are only flushed when full.

The buffering associated with a stream can always be flushed by using fflush explicitly. Support for the various types of buffering is implementation defined, and can be controlled within these limits using setbuf and setvbuf.

10.5. Direct file manipulation

A number of functions exist to operate on files directly.

#include <stdio.h>

int remove(const char *filename);
int rename(const char *old, const char *new);
char *tmpnam(char *s);
FILE *tmpfile(void);


Causes a file to be removed. Subsequent attempts to open the file will fail, unless it is first created again. If the file is already open, the operation of remove is implementation defined. The return value is zero for success, any other value for failure.


Changes the name of the file identified by old to new. Subsequent attempts to open the original name will fail, unless another file is created with the old name. As with remove, rename returns zero for a successful operation, any other value indicating a failure.

If a file with the new name exists prior to calling rename, the behaviour is implementation defined.

If rename fails for any reason, the original file is unaffected.


Generates a string that may be used as a filename and is guaranteed to be different from any existing filename. It may be called repeatedly, each time generating a new name. The constant TMP_MAX is used to specify how many times tmpnam may be called before it can no longer find a unique name. TMP_MAX will be at least 25. If tmpnam is called more than this number of times, its behaviour is undefined by the Standard, but many implementations offer no practical limit.

If the argument s is set to NULL, then tmpnam uses an internal buffer to build the name, and returns a pointer to that. Subsequent calls may alter the same internal buffer. The argument may instead point to an array of at least L_tmpnam characters, in which case the name will be filled into the supplied buffer. Such a filename may then be created, and used as a temporary file. Since the name is generated by the function, it is unlikely to be very useful in any other context. Temporary files of this nature are not removed, except by direct calls to the remove function. They are most often used to pass temporary data between two separate programs.


Creates a temporary binary file, opened for update, and returns a pointer to the stream of that file. The file will be removed when the stream is closed. If no file could be opened, tmpfile returns a null pointer.

10.6. Opening named files

Named files are opened by a call to the fopen function, whose declaration is this:

#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);

The pathname argument is the name of the file to open, such as that returned from tmpnam, or some program-specific filename.

Files can be opened in a variety of modes, such as read mode for reading data, write mode for writing data, and so on.

Note that if you only want to write data to a file, fopen will create the file if it does not already exist, or truncate it to zero length (losing its previous contents) if it did exist.

The Standard list of modes is shown in Table 3, although implementations may permit extra modes by appending extra characters at the end of the modes.


Type of file































































































Table 3. File opening modes

Beware that some implementations of binary files may pad the last record with NULL characters, so opening them with modes ab, ab+ or a+b could position the file pointer beyond the last data written.

If a file is opened in append mode, all writes will occur at the end of the file, regardless of attempts to move the file position indicator with fseek. The initial position fo the file position indicator will be implementation defined.

Attempts to open a file in read mode, indicated by an 'r' as the first character in the mode string, will fail if the file does not already exist or can't be read.

Files opened for update (' ' as the second or third character of mode) may be both read and written, but a read may not immediately follow a write, or a write follow a read, without an intervening call to one (or more) of fflush, fseek, fsetpos or rewind. The only exception is that a write may immediately follow a read if EOF was read.

It may also be possible in some implementations to omit the b in the binary modes, using the same modes for text and binary files.

Streams opened by fopen are fully buffered only if they are not connected to an interactive device; this ensures that prompts and responses are handled properly.

If fopen fails to open a file, it returns a null pointer; otherwise, it returns a pointer to the object controlling the stream. The stdin, stdout and stderr objects are not necessarily modifiable and it may not be possible to use the value returned from fopen for assignment to one of them. For this reason, freopen is provided.

10.7. Freopen

The freopen function is used to take an existing stream pointer and associate it with another named file:

#include <stdio.h>
FILE *freopen(const char *pathname,
const char *mode, FILE *stream);

The mode argument is the same as for fopen. The stream is closed first, and any errors from the close are ignored. On error, NULL is returned, otherwise the new value for stream is returned.

10.8. Closing files

An open file is closed using fclose.

#include <stdio.h>

int fclose(FILE *stream);

Any unwritten data buffered for stream is flushed out and any unread data is thrown away. If a buffer had been automatically allocated for the stream, it is freed. The file is then closed.

Zero is returned on success, EOF if any error occurs.

10. Setbuf, setvbuf

These two functions are used to change the buffering strategy for an open stream:

#include <stdio.h>

int setvbuf(FILE *stream, char *buf,
int type, size_t size);
void setbuf(FILE *stream, char *buf);

They must be used before the file is either read from or written to. The type argument defines how the stream will be buffered (see Table 4).




Do not buffer I/O


Fully buffer I/O


Line buffer: flush buffer when full, when newline is written or when a read is requested.

Table 4. Type of buffering

The buf argument can be a null pointer, in which case an array is automatically allocated to hold the buffered data. Otherwise, the user can provide a buffer, but should ensure that its lifetime is at least as long as that of the stream: a common mistake is to use automatic storage allocated inside a compound statement; in correct usage it is usual to obtain the storage from malloc instead. The size of the buffer is specified by the size argument.

A call of setbuf is exactly the same as a call of setvbuf with IOFBF for the type argument, and BUFSIZ for the size argument. If buf is a null pointer, the value _IONBF is used for type instead.

No value is returned by setbuf, setvbuf returns zero on success, non-zero if invalid values are provided for type or size, or the request cannot be complied with.

10.10. Fflush

#include <stdio.h>

int fflush(FILE *stream);

If stream refers to a file opened for output or update, any unwritten data is 'written' out. Exactly what that means is a function of the host environment, and C cannot guarantee, for example, that data immediately reaches the surface of a disk which might be supporting the file. If the stream is associated with a file opened for input or update, any preceding ungetc operation is forgotten.

The most recent operation on the stream must have been an output operation; if not, the behaviour is undefined.

A call of fflush with an argument of zero flushes every output or update stream. Care is taken to avoid those streams that have not had an output as their last operation, thus avoiding the undefined behaviour mentioned above.

EOF is returned if an error occurs, otherwise zero.

11. Formatted I/O

There are a number of related functions used for formatted I/O, each one determining the format of the I/O from a format string. For output, the format string consists of plain text, which is output unchanged, and embedded format specifications which call for some special processing of one of the remaining arguments to the function. On input, the plain text must match what is seen in the input stream; the format specifications again specify what the meaning of remaining arguments is.

Each format specification is introduced by a character, followed by the rest of the specification.

11.1. Output: the printf family

For those functions performing output, the format specification takes the following form, with optional parts enclosed in brackets:

%<flags><field width><precision><length>conversion

The meaning of flags, field width, precision, length, and conversion are given below, although tersely. For more detail, it is worth looking at what the Standard says.


Zero or more of the following:

Left justify the conversion within its field.

A signed conversion will always start with a plus or minus sign.


If the first character of a signed conversion is not a sign, insert a space. Overridden by if present.

Forces an alternative form of output. The first digit of an octal conversion will always be a ; inserts 0X in front of a non-zero hexadecimal conversion; forces a decimal point in all floating point conversions even if one is not necessary; does not remove trailing zeros from g and G conversions.

Pad d, i, o, u, x, X, e, E, f, F and G conversions on the left with zeros up to the field width. Overidden by the  flag. If a precision is specified for the d, i, o, u, x or X conversions, the flag is ignored. The behaviour is undefined for other conversions.

field width

A decimal integer specifying the minimum output field width. This will be exceeded if necessary. If an asterisk is used here, the next argument is converted to an integer and used for the value of the field width; if the value is negative it is treated as a  flag followed by a positive field width. Output that would be less than the field width is padded with spaces (zeros if the field width integer starts with a zero) to fit. The padding is on the left unless the left-adjustment flag is specified.


This starts with a period ' '. It specifies the minimum number of digits for d, i, o, u, x, or X conversions; the number of digits after the decimal point for e, E, f conversions; the maximum number of digits for g and G conversions; the number of characters to be printed from a string for s conversion. The amount of padding overrides the field width. If an asterisk is used here, the next argument is converted to an integer and used for the value of the field width. If the value is negative, it is treated as if it were missing. If only the period is present, the precision is taken to be zero.


h preceding a specifier to print an integral type causes it to be treated as if it were a short. (Note that the various sorts of short are always promoted to one of the flavours of int when passed as an argument.) l works like h but applies to a long integral argument. L is used to indicate that a long double argument is to be printed, and only applies to the floating-point specifiers. These are cause undefined behaviour if they are used with the 'wrong' type of conversion.


See Table 5.



Default precision


signed decimal



signed decimal



unsigned decimal



unsigned octal



unsigned hexadecimal ( -f)



unsigned hexadecimal ( -F)


Precision specifies minimum number of digits, expanded with leading zeros if necessary. Printing a value of zero with zero precision outputs no characters.


Print a double with precision digits (rounded) after the decimal point. To suppress the decimal point use a precision of explicitly zero. Otherwise, at least one digit appears in front of the point.


e, E

Print a double in exponential format, rounded, with one digit before the decimal point, precision after it. A precision of zero suppresses the decimal point. There will be at least two digits in the exponent, which is printed as 1.23e15 in e format, or 1.23E15 in E format.



Use style f, or e (E with G) depending on the exponent. If the exponent is less than −4 or ≥ precision, f is not used. Trailing zeros are suppressed, a decimal point is only printed if there is a following digit.



The int argument is converted to an unsigned char and the resultant character printed.


Print a string up to precision digits long. If precision is not specified, or is greater than the length of the string, the string must be NUL terminated.



Display the value of a (void *) pointer in a system-dependent way.


The argument must be a pointer to an integer. The number of characters output so far by this call will be written into the integer.



Table 5. Conversions

The functions that use these formats are described in Table 6. All need the inclusion of <stdio.h>. Their declarations are as shown.

#include <stdio.h>

int fprintf(FILE *stream, const char *format, );
int printf(const char *format, );
int sprintf(char *s, const char *format, );

#include <stdarg.h> /* as well as stdio.h */
int vfprintf(FILE *stream, const char *format, va list arg);
int vprintf(const char *format, va list arg);
int vsprintf(char *s, const char *format, va list arg);




General formatted output as described. Output is written to the file indicated by stream.


Identical to fprintf with a first argument equal to stdout.


Identical to fprintf except that the output is not written to a file, but written into the character array pointed to by s.


Formatted output as for fprintf, but with the variable argument list replaced by arg which must have been initialized by va_start. va_end is not called by this function.


Identical to vfprintf with a first argument equal to stdout.


Formatted output as for sprintf, but with the variable argument list replaced by arg which must have been initialized by va_start. va_end is not called by this function.

Table 6. Functions performing formatted output

All of the above functions return the number of characters output, or a negative value on error. The trailing null is not counted by sprintf and vsprintf.

Implementations must permit at least 509 characters to be produced by any single conversion.

11.2. Input: the scanf family

A number of functions exist analogous to the printf family, but for the purposes of input instead. The most immediate difference between the two families is that the scanf group needs to be passed pointers to their arguments, so that the values read can be assigned to the proper destinations. Forgetting to pass a pointer is a very common error, and one which the compiler cannot detect-the variable argument list prevents it.

The format string is used to control interpretation of a stream of input data, which generally contains values to be assigned to the objects pointed to by the remaining arguments to scanf. The contents of the format string may contain:

white space

This causes the input stream to be read up to the next non-white-space character.

ordinary character

Anything except white-space or characters. The next character in the input stream must match this character.

conversion specification

This is a character, followed by an optional character (which suppresses the conversion), followed by an optional nonzero decimal integer specifying the maximum field width, an optional h, l or L to control the length of the conversion and finally a non-optional conversion specifier. Note that use of h, l, or L will affect the type of pointer which must be used.

Except for the specifiers c, n and , a field of input is a sequence of non-space characters starting at the first non-space character in the input. It terminates at the first conflicting character or when the input field width is reached.

The result is put into wherever the corresponding argument points, unless the assignment is suppressed using the mentioned already. The following conversion specifiers may be used:

d i o u x

Convert a signed integer, a signed integer in a form acceptable to strtol, an octal integer, an unsigned integer and a hexadecimal integer respectively.

e f g

Convert a float (not a double).


Read a string, and add a null at the end. The string is terminated by whitespace on input (which is not read as part of the string).

Read a string. A list of characters, called the scan set follows the . A delimits the list. Characters are read until (but not including) the first character which is not in the scan set. If the first character in the list is a circumflex , then the scan set includes any character not in the list. If the initial sequence is or , the ] is not a delimiter, but part of the list and another will be needed to end the list. If there is a minus sign ( ) in the list, it must be either the first or the last character; otherwise the meaning is implementation defined.


Read a single character; white space is significant here. To read the first non-white space character, use %1s. A field width indicates that an array of characters is to be read.


Read a (void *) pointer previously written out using the %p of one of the printfs.

A is expected in the input, no assignment is made.


Return as an integer the number of characters read by this call so far.

The size specifiers have the effect shown in Table 7.





d i o u x

long int


d i o u x

short int


e f



e f

long double

Table 7. Size specifiers

The functions are described below, with the following declarations:

#include <stdio.h>

int fscanf(FILE *stream, const char *format, );
int sscanf(const char *s, const char *format, );
int scanf(const char *format, );

Fscanf takes its input from the designated stream, scanf is identical to fscanf with a first argument of stdin, and sscanf takes its input from the designated character array.

If an input failure occurs before any conversion, EOF is returned. Otherwise, the number of successful conversions is returned: this may be zero if no conversions are performed.

An input failure is caused by reading EOF or reaching the end of the input string (as appropriate). A conversion failure is caused by a failure to match the proper pattern for a particular conversion.

12. Character I/O

A number of functions provide for character oriented I/O. Their declarations are:

#include <stdio.h>
/* character input */
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);
int ungetc(int c, FILE *stream);

/* character output */
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);

/* string input */
char *fgets(char *s, int n, FILE *stream);
char *gets(char *s);

/* string output */
int fputs(const char *s, FILE *stream);
int puts(const char *s);

Their descriptions are as follows.

12.1. Character input

These read an unsigned char from the input stream where specified, or otherwise stdin. In each case, the next character is obtained from the input stream. It is treated as an unsigned char and converted to an int, which is the return value. On End of File, the constant EOF is returned, and the end-of-file indicator is set for the associated stream. On error, EOF is returned, and the error indicator is set for the associated stream. Successive calls will obtain characters sequentially. The functions, if implemented as macros, may evaluate their stream argument more than once, so do not use side effects here.

There is also the supporting ungetc routine, which is used to push back a character on to a stream, causing it to become the next character to be read. This is not an output operation and can never cause the external contents of a file to be changed. A fflush, fseek, or rewind operation on the stream between the pushback and the read will cause the pushback to be forgotten. Only one character of pushback is guaranteed, and attempts to pushback EOF are ignored. In every case, pushing back a number of characters then reading or discarding them leaves the file position indicator unchanged. The file position indicator is decremented by every successful call to ungetc for a binary stream, but unspecified for a text stream, or a binary stream which is positioned at the beginning of the file.

12.2. Character output

These are identical in description to the input functions already described, except performing output. They return the character written, or EOF on error. There is no equivalent to End of File for an output file.

12.3. String output

These write strings to the output file; stream where specified, otherwise stdout. The terminating null is not written. Non-zero is returned on error, zero otherwise. Beware: puts appends a newline to the string output; fputs does not!

12.4. String input

Fgets reads a string into the array pointed to by s from the stream stream. It stops on either EOF or the first newline (which it reads), and appends a null character. At most n−1 characters are read (leaving room for the null).

Gets works similarly for the stream stdin, but discards the newline!

Both return s if successful, or a null pointer otherwise. In each case, if EOF is encountered before any characters have been read, the array is unchanged and a null pointer is returned. A read error in the middle of a string leaves the array contents undefined and a null pointer is returned.

13. Unformatted I/O

This is simple: only two functions provide this facility, one for reading and one for writing:

#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nelem, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nelem, FILE *stream);

In each case, the appropriate read or write is performed on the data pointed to by ptr. Up to nelem elements, of size size, are transferred. Failure to transfer the full number is an error only when writing; End of File can prevent the full number on input. The number of elements actually transferred is returned. To distinguish between End of File on input, or an error, use feof or ferror.

If size or nelem is zero, fread does nothing except to return zero.

An example may help.

#include <stdio.h>
#include <stdlib.h>

struct xxar[20];



if(fread((void *)&ar[10],
sizeof(ar[0]), 5, fp) != 5)

Example 7

14. Random access functions

The file I/O routines all work in the same way; unless the user takes explicit steps to change the file position indicator, files will be read and written sequentially. A read followed by a write followed by a read (if the file was opened in a mode to permit that) will cause the second read to start immediately following the end of the data just written. (Remember that stdio insists on the user inserting a buffer-flushing operation between each element of a read-write-read cycle.) To control this, the Random Access functions allow control over the implied read/write position in the file. The file position indicator is moved without the need for a read or a write, and indicates the byte to be the subject of the next operation on the file.

Three types of function exist which allow the file position indicator to be examined or changed. Their declarations and descriptions follow.

#include <stdio.h>

/* return file position indicator */
long ftell(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);

/* set file position indicator to zero */
void rewind(FILE *stream);

/* set file position indicator */
int fseek(FILE *stream, long offset, int ptrname);
int fsetpos(FILE *stream, const fpos_t *pos);

Ftell returns the current value (measured in characters) of the file position indicator if stream refers to a binary file. For a text file, a 'magic' number is returned, which may only be used on a subsequent call to fseek to reposition to the current file position indicator. On failure, -1L is returned and errno is set.

Rewind sets the current file position indicator to the start of the file indicated by stream. The file's error indicator is reset by a call of rewind. No value is returned.

Fseek allows the file position indicator for stream to be set to an arbitrary value (for binary files), or for text files, only to a position obtained from ftell, as follows:

  • In the general case, the file position indicator is set to offset bytes (characters) from a point in the file determined by the value of ptrname. Offset may be negative. The values of ptrname may be SEEK_SET, which sets the file position indicator relative to the beginning of the file, SEEK_CUR, which sets the file position indicator relative to its current value, and SEEK_END, which sets the file position indicator relative to the end of the file. The latter is not necessarily guaranteed to work properly on binary streams.
  • For text files, offset must either be zero or a value returned from a previous call to ftell for the same stream, and the value of ptrname must be SEEK_SET.
  • Fseek clears the end of file indicator for the given stream and erases the memory of any ungetc. It works for both input and output.
  • Zero is returned for success, non-zero for a forbidden request.

Note that for ftell and fseek it must be possible to encode the value of the file position indicator into a long. This may not work for very long files, so the Standard introduces fgetpos and fsetpos which have been specified in a way that removes the problem.

Fgetpos stores the current file position indicator for stream in the object pointed to by pos. The value stored is 'magic' and only used to return to the specified position for the same stream using fsetpos.

Fsetpos works as described above, also clearing the stream's end-of-file indicator and forgetting the effects of any ungetc operations.

For both functions, on success, zero is returned; on failure, non-zero is returned and errno is set.

14.1. Error handling

The standard I/O functions maintain two indicators with each open stream to show the end-of-file and error status of the stream. These can be interrogated and set by the following functions:

#include <stdio.h>

void clearerr(FILE *stream);

int feof(FILE *stream);

int ferror(FILE *stream);

void perror(const char *s);

Clearerr clears the error and EOF indicators for the stream.

Feof returns non-zero if the stream's EOF indicator is set, zero otherwise.

Ferror returns non-zero if the stream's error indicator is set, zero otherwise.

Perror prints a single-line error message on the program's standard output, prefixed by the string pointed to by s, with a colon and a space appended. The error message is determined by the value of errno and is intended to give some explanation of the condition causing the error. For example, this program produces the error message shown:

#include <stdio.h>
#include <stdlib.h>


/* Result */
fgetc: Bad file number

Example 8

Well, we didn't say that the message had to be very meaningful!

15. General Utilities

These all involve the use of the header <stdlib.h>, which declares a number of types and macros and several functions of general use. The types and macros are as follows:


Described at the start of this chapter.


This is the type of the structure returned by div.


This is the type of the structure returned by ldiv.


Again, described at the start of this chapter.



These may be used as arguments to exit.


The maximum number of bytes in a multibyte character from the extended character set specified by the current locale.


This is the maximum value returned by the rand function.

15.1. String conversion functions

Three functions take a string as an argument and convert it to a number of the type shown below:

#include <stdlib.h>

double atof(const char *nptr);
long atol(const char *nptr);
int atoi(const char *nptr);

For each of the functions, the number is converted and the result returned. None of them guarantees to set errno (although they may do in some implementations), and the results of a conversion which overflows or cannot be represented is undefined.

More sophisticated functions are:

#include <stdlib.h>

double strtod(const char *nptr, char **endptr);
long strtol(const char *nptr, char **endptr, int base);
unsigned long strtoul(const char *nptr,char **endptr, int base);

All three functions work in a similar way. Leading white space is skipped, then a subject sequence, resembling an appropriate constant, is found, followed by a sequence of unrecognized characters. The trailing null at the end of a string is always unrecognized. The subject sequence can be empty. The subject sequences are determined as follows:


Optional or , followed by a digit sequence containing an optional decimal point character, followed by an optional exponent. No floating suffix will be recognized. If there is no decimal point present, it is assumed to follow the digit sequence.


Optional or , followed by a digit sequence. The digits are taken from the decimal digits or an upper or lower case letter in the range a-z of the English alphabet; the letters are given the values 10-35 respectively. The base argument determines which values are permitted, and may be zero, or otherwise 2-36. Only 'digits' with a value less than that of base are recognized. A base of 16 permits the characters 0x or 0X to follow the optional sign. A base of zero permits the input of characters in the form of a C integer constant. No integer suffix will be recognized.


Identical to strtol but with no sign permitted.

If endptr is non-null, the address of the first unrecognized character is stored in the object that it points to. If the subject sequence is empty or has the wrong form, this is the value of nptr.

If a conversion can be performed, the functions convert the number and return its value, taking into account a leading sign where permitted. Otherwise they return zero. On overflow or error the action is as follows:


On overflow, returns HUGE_VAL according to the sign of the result; on underflow, returns zero. In either case, errno is set to ERANGE.


On overflow, LONG_MAX or LONG_MIN is returned according to the sign of the result, errno is set to ERANGE.


On overflow, ULONG_MAX is returned, errno is set to ERANGE.

If the locale is not the 'C' locale, there may be other subject sequences recognised depending on the implementation.

15.2. Random number generation

Provision for pseudo-random number generation is made by the following functions.

#include <stdlib.h>

int rand(void);
void srand(unsigned int seed);

Rand returns a pseudo-random number in the range to RAND_MAX, which has a value of at least .

Srand allows a given starting point in the sequence to be chosen according to the value of seed. If srand is not called before rand, the value of the seed is taken to be . The same sequence of values will always be returned from rand for a given value of seed.

The Standard describes an algorithm which may be used to implement rand and srand. In practice, most implementations will probably use this algorithm.

15.3. Memory allocation

These functions are used to allocate and free storage. The storage so obtained is only guaranteed to be large enough to store an object of the specified type and aligned appropriately so as not to cause addressing exceptions. No further assumptions can be made.

#include <stdlib.h>

void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);

void *free(void *ptr);

All of the memory allocation functions return a pointer to allocated storage of size size bytes. If there is no free storage, they return a null pointer. The differences between them are that calloc takes an argument nmemb which specifies the number of elements in an array, each of whose members is size bytes, and so allocates a larger piece of store (in general) than malloc. Also, the store allocated by malloc is not initialized, whereas calloc sets all bits in the storage to zero. This is not necessarily the equivalent representation of floating-point zero, or the null pointer.

Realloc is used to change the size of the thing pointed to by ptr, which may require some copying to be done and the old storage freed. The contents of the object pointed to by ptr is unchanged up to the smaller of the old and the new sizes. If ptr is null, the behaviour is identical to malloc with the appropriate size.

Free is used to free space previously obtained with one of the allocation routines. It is permissible to give free a null pointer as the argument, in which case nothing is done.

If an attempt is made to free store which was never allocated, or has already been freed, the behaviour is undefined. In many environments this causes an addressing exception which aborts the program, but this is not a reliable indicator.

15.4. Communication with the environment

A miscellany of functions is found here.

#include <stdlib.h>

void abort(void);
int atexit(void (*func)(void));
void exit(int status);
char *getenv(const char *name);
int system(const char *string);


Causes abnormal program termination to occur, by raising the SIGABRT signal. Abnormal termination is only prevented if the signal is being caught, and the signal handler does not return. Otherwise, output files may be flushed and temporary files may be removed according to implementation definition, and an 'unsuccessful termination' status returned to the host environment. This function cannot return.


The argument func becomes a function to be called, without arguments, when the program terminates. Up to at least 32 such functions may be registered, and are called on program termination in reverse order of their registration. Zero is returned for success, non-zero for failure.


Normal program termination occurs when this is called. First, all of the functions registered using atexit are called, but beware-by now, main is considered to have returned and no objects with automatic storage duration may safely be used. Then, all the open output streams are flushed, then closed, and all temporary files created by tmpfile are removed. Finally, the program returns control to the host environment, returning an implementation-defined form of successful or unsuccessful termination status depending on whether the argument to exit was EXITSUCCESS or EXIT FAILURE respectively. For compatibility with Old C, zero can be used in place of EXITSUCCESS, but other values have implementation-defined effects. Exit cannot return.


The implementation-defined environment list is searched to find an item which corresponds to the string pointed to by name. A pointer to the item is returned-it points to an array which must not be modified by the program, but may be overwritten by a subsequent call to getenv. A null pointer is returned if no item matches.

The purpose and implementation of the environment list depends on the host environment.


An implementation-defined command processor is passed the string string. A null pointer will cause a return of zero if no command processor exists, non-zero otherwise. A non-null pointer causes the command to be processed. The effect of the command and the value returned are implementation defined.

15.5. Searching and sorting

Two functions exist in this category: one for searching an already sorted list, the other for sorting an unsorted list. They are completely general, handling arrays of arbitrary size with elements of arbitrary size.

To enable them to compare two elements, the user provides a comparison function, which is called with pointers to two of the elements as its arguments. It returns a value less than, equal to or greater than zero depending on whether the first pointer points to an element considered to be less than, equal to or greater than the object pointed to by the second pointer, respectively.

#include <stdlib.h>

void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));

void *qsort(const void *base, size_t nmemb,
size_t size,
int (*compar)(const void *, const void *));

For both functions, nmemb is the number of elements in the array, size is the size in bytes of an array element and compar is the function to be called to compare them. Base is a pointer to the base of the array.

Qsort will sort the array into ascending order.

Bsearch assumes that the array is already sorted and returns a pointer to any element it finds that compares equal to the object pointed to by key. A null pointer is returned if no match is found.

15.6. Integer arithmetic functions

These provide ways of finding the absolute value of an integral argument and the quotient and remainder of a division, for both int and long types.

#include <stdlib.h>

int abs(int j);
long labs(long j);

div_t div(int numerator, int denominator);
ldiv_t ldiv(long numerator, long denominator);



These return the absolute value of their argument-choose the appropriate one for your needs. The behaviour is undefined if the value cannot be represented-this can happen in two's complement systems where the most negative number has no positive equivalent.



These divide the numerator by the denominator and return a structure of the indicated type. In each case the structure will contain a member called quot which contains the quotient of the division truncated towards zero, and a member called rem which will contain the remainder. The type of each member is int for div and long for ldiv. Provided that the result could be represented, quot*denominator+rem == numerator.

15.7. Functions using multibyte characters

The LC_CTYPE category of the current locale affects the behaviour of these functions. For an encoding that is state-dependent, each function is put in its initial state by a call in which its character pointer argument, s, is a null pointer. The internal state of the function is altered as necessary by subsequent calls when s is not a null pointer. If s is a null pointer, the functions return a non-zero value if encodings are state-dependent, otherwise zero. If the LC_CTYPE category is changed, the shift state of the functions will become indeterminate.

The functions are:

#include <stdlib.h>

int mblen(const char *s, size_t n);
int mbtowc(wchar_t *pwc, const char *s, size_t n);
int wctomb(char *s, wchar_t wchar);
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n);
size_t wcstombs(char *s, const wchar_t *pwcs, size_t n);


Returns the number of bytes that are contained in the multibyte character pointed to by s, or −1 if the first n bytes do not form a valid multibyte character. If s points to the null character, zero is returned.


Converts the multibyte character pointed to by s to the corresponding code of type wchar_t and stores the result in the object pointed to by pwc, unless pwc is a null pointer. Returns the number of bytes successfully converted, or −1 if the first n bytes do not form a valid multibye character. No more than n bytes pointed to by s are examined. The value returned will not be more than n or MB_CUR_MAX.


Converts the code whose value is in wchar to a sequence of bytes representing the corresponding multibyte character, and stores the result in the array pointed to by s, if s is not a null pointer. Returns the number of bytes that are contained in the multibyte character, or −1 if the value in wchar does not correspond to a valid multibyte character. At most, MB_CUR_MAX bytes are processed.


Converts the sequence of multibyte characters, beginning in the initial shift state, in the array pointed to by s, into a sequence of corresponding codes which are then stored in the array pointed to by pwcs. Not more than n values will be placed in pwcs. Returns −1 if an invalid multibyte character is encountered, otherwise returns the number of array elements modified, excluding the terminating null-code.

If the two objects overlap, the behaviour is undefined.


Converts the sequence of codes pointed to by pwcs to a sequence of multibyte characters, beginning in the initial shift state, which are then stored in the array pointed to by s. Conversion stops when either a null-code is encountered or n bytes have been written to s. Returns −1 if a code is encountered which does not correspond to a valid multibyte character, otherwise the number of bytes written, excluding the terminating null-code.

If the two objects overlap, the behaviour is undefined.

16. String handling

Numerous functions exist to handle strings. In C, a string is an array of characters terminated by a null. In all cases, the functions expect a pointer to the first character in the string. The header <string.h> declares these functions.

16.1. Copying

The functions for this purpose are:

#include <string.h>

void *memcpy(void *s1, const void *s2, size_t n);
void *memmove (void *s1, const void *s2, size_t n);
char *strcpy(char *s1, const char *s2);
char *strncpy(char *s1, const char *s2, size_t n);
char *strcat(char *s1, const char *s2);
char *strncat(char *s1, const char *s2, size_t n);


This copies n bytes from the place pointed to by s2 to the place pointed to by s1. If the objects overlap, the result is undefined. The value of s1 is returned.


Identical to memcpy, but works even for overlapping objects. It may be marginally slower, though.



Both of these copy the string pointed to by s2 into the string pointed to by s1, including the trailing null. Strncpy will copy at most n characters, and pad with trailing nulls if s2 is shorter than n characters. If the strings overlap, the behaviour is undefined. They return s1.



Both append the string in s2 to s1, overwriting the null at the end of s1. A final null is always written. At most n characters are copied from s2 by strncat, which means that for safety the destination string should have room for its original length (not counting the null) plus n + 1 characters. They return s1.

16.2. String and byte comparison

These comparison functions are used to compare arrays of bytes. This obviously includes the traditional C strings, which are an array of char (bytes) with a terminating null. All of these functions work by comparing a byte at a time, and stopping either when two bytes differ (in which case they return the sign of the difference between the two bytes), or the arrays are considered to be equal: no differences were found, and the length of the arrays was equal to the specified amount, or the null was found at the end of a string comparison.

For all except strxfrm, the value returned is less than, equal to or greater than zero depending on whether the first object was considered to be less than, equal to or greater than the second.

#include <string.h>

int memcmp(const void *s1, const void *s2, size_t n);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
size_t strxfrm(char *to, const char *from,
int strcoll(const char *s1, const char *s2);


Compares the first n characters in the objects pointed to by s1 and s2. It is very dodgy to compare structures in this way, because unions or 'holes' caused by alignment padding can contain junk.


Compares the two strings. This is one of the most commonly used of the string-handling functions.


As for strcmp, but compares at most n characters.


The string in from is converted (by some magic), and placed wherever to points. At most maxsize characters (including the trailing null) are written into the destination. The magic guarantees that two such transformed strings will give the same comparison with each other for the user's current locale when using strcmp, as when strcoll is applied to the original two strings.

In all cases, the length of the resulting string (not counting its terminating null) is returned. If the value is equal to or greater than maxsize, the contents of *to is undefined. If maxsize is zero, s1 may be a null pointer.

If the two objects overlap, the behaviour is undefined.


This function compares the two strings according to the collating sequence specified by the current locale.

16.3. Character and string searching functions

#include <string.h>

void *memchr(const void *s, int c, size_t n);
char *strchr(const char *s, int c);
size_t strcspn(const char *s1, const char *s2);
char *strpbrk(const char *s1, const char *s2);
char *strrchr(const char *s, int c);
size_t strspn(const char *s1, const char *s2);
char *strstr(const char *s1, const char *s2);
char *strtok(const char *s1, const char *s2);


Returns a pointer to the first occurrence in the initial n characters of *s of the (unsigned char)c. Returns null if there is no such occurrence.


Returns a pointer to the first occurrence of (char)c in *s, including the null in the search. Returns null if there is no such occurrence.


Returns the length of the initial part of the string s1 which contains no characters from s2. The terminating null is not considered to be part of s2.


Returns a pointer to the first character in s1 which is any of the characters in s2, or null if there is none.


Returns a pointer to the last occurrence in s1 of (char)c counting the null as part of s1, or null if there is none.


Returns the length of the initial part of s1 consisting entirely of characters from s1.


Returns a pointer to the first occurrence in s1 of the string s2, or null if there is none.


Breaks the string in s1 into 'tokens', each delimited by one of the characters from s2 and returns a pointer to the first token, or null if there is none. Subsequent calls with (char *)0 as the value of s1 return the next token in sequence, with the extra fun that s2 (and hence the delimiters) may differ on each subsequent call. A null pointer is returned if no tokens remain.

16.4. Miscellaneous functions

#include <string.h>

void *memset(void *s, int c, size_t n);
char *strerror(int errnum);
size_t strlen(const char *s);


Sets the n bytes pointed to by s to the value of (unsigned char)c. Returns s.


Returns the length of the string s not counting the terminating null. This is a very widely used function.


Returns a pointer to a string describing the error number errnum. This string may be changed by subsequent calls to strerror. Useful for finding out what the values in errno mean.

17. Date and time

These functions deal with either 'elapsed' or 'calendar' time. They share the <time.h> header, which declares the functions as necessary and also the following:


This is the number of 'ticks' per second returned by the clock function.



These are arithmetic types used to represent different forms of time.

struct tm

This structure is used to hold the values representing a calendar time. It contains the following members, with the meanings as shown.

int tm_sec /* seconds after minute [0-61] (61 allows for 2 leap-seconds)*/
int tm_min /* minutes after hour [0-59] */
int tm_hour /* hours after midnight [0-23] */
int tm_mday /* day of the month [1-31] */
int tm_mon /* month of year [0-11] */
int tm_year /* current year-1900 */
int tm_wday /* days since Sunday [0-6] */
int tm_yday /* days since January 1st [0-365] */
int tm_isdst /* daylight savings indicator */

The tm_isdst member is positive if daylight savings time is in effect, zero if not and negative if that information is not available.

The time manipulation functions are the following:

#include <time.h>

clock_t clock(void);
double difftime(time_t time1, time_t time2);
time_t mktime(struct tm *timeptr);
time_t time(time_t *timer);
char *asctime(const struct tm *timeptr);
char *ctime(const time_t *timer);
struct tm *gmtime(const time_t *timer);
struct tm *localtime(const time_t *timer);
size_t strftime(char *s, size_t maxsize,
const char *format,
const struct tm *timeptr);

The functions asctime, ctime, gmtime, localtime, and strftime all share static data structures, either of type struct tm or char [], and calls to one of them may overwrite the data stored by a previous call to one of the others. If this is likely to cause problems, their users should take care to copy any values needed.


Returns the best available approximation to the time used by the current invocation of the program, in 'ticks'. (clock_t)-1 is returned if no value is available. To find the actual time used by a run of a program, it is necessary to find the difference between the value at the start of the run and the time of interest-there is an implementation-defined constant factor which biases the value returned from clock. To determine the time in seconds, the value returned should be divided by CLOCKS_PER_SEC.


This returns the difference in seconds between two calendar times.


This returns the calendar time corresponding to the values in a structure pointed to by timeptr, or (time_t)-1 if the value cannot be represented.

The tm_wday and tm_yday members of the structure are ignored, the other members are not restricted to their usual values. On successful conversion, the members of the structure are all set to appropriate values within their normal ranges. This function is useful to find out what value of a time_t corresponds to a known date and time.


Returns the best approximation to the current calendar time in an unspecified encoding. (time_t)-1 is returned if the time is not available.


Converts the time in the structure pointed to by timeptr into a string of the form

Sun Sep 16 01:03:52 1973n0

the example being taken from the Standard. The Standard defines the algorithm used, but the important point to notice is that all the fields within that string are of constant width and relevant to most English-speaking communities. The string is stored in a static structure which may be overwritten by a subsequent call to one of the other time-manipulation functions (see above).


Equivalent to asctime(localtime(timer)). See asctime for the return value.


Returns a pointer to a struct tm set to represent the calendar time pointed to by timer. The time is expressed in terms of Coordinated Universal Time (UTC) (formerly Greenwich Mean Time). A null pointer is returned if UTC is not available.


Converts the time pointed to by timer into local time and puts the results into a struct tm, returning a pointer to that structure.


Fills the character array pointed to by s with at most maxsize characters. The format string is used to format the time represented in the structure pointed to timeptr. Characters in the format string (including the terminating null) are copied unchanged into the array, unless one of the following format directives is found-then the value specified below is copied into the destination, as appropriate to the locale.


abbreviated weekday name


full weekday name


abbreviated month name


full month name


date and time representation


decimal day of month number 01-31


hour 00-23 (24 hour format)


hour 01-12 (12 hour format)


day of year 001-366


month 01-12


minute 00-59


local equivalent of 'AM' or 'PM'


second 00-61


week number in year 00-53 (Sunday is first day of week


weekday, 0-6 (Sunday is 0)


week number in year 00-53 (Monday is first day of week


local date representation


local time representation


year without century prefix 00-99


year with century prefix


timezone name, or no characters if no timezone exists

a character

The total number of characters copied into *s is returned, excluding the null. If there was not room (as determined by maxsize) for the trailing null, zero is returned.

18. Summary

It will almost certainly be the standardization of the run-time library that has the most effect on the portability of C programs. Prospective users of C really should read through this chapter carefully and familiarize themselves with its contents. The lack of a widely implemented, portable library was historically the biggest single barrier to portability.

If you are writing programs for embedded systems, bad luck! The library is not defined for stand-alone applications, but in practice we can expect suppliers to produce a stand-alone library package too. It will probably come without the file handling, but there is no reason why, say, the string-handling functions should not work just as well in hosted and unhosted environments.

Politica de confidentialitate | Termeni si conditii de utilizare



Vizualizari: 798
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved