Prev | Contents | Next

6 <errno.h> Error Information

Variable Description
errno Holds the error status of the last call

This header defines a single variable15, errno, that can be checked to see if an error has occurred.

errno is set to 0 on startup, but no library function sets it to 0. If you’re going to use solely it to check for errors, set it to 0 before the call and then check it after. Not only that, but if there’s no error, all library functions will leave the value of errno unchanged.

Often, though, you’ll get some error indication from the function you’re calling then check errno to see what went wrong.

This is commonly used in conjunction with perror() to get a human-readable error message that corresponds to the specific error.

Important Safety Tip: You should never make your own variable called errno—that’s undefined behavior.

Note that the C Spec defines less than a handful of values errno can take on. Unix defines a bunch more16, as does Windows17.


6.1 errno

Holds the error status of the last call

Synopsis

errno   // Type is undefined, but it's assignable

Description

Indicates the error status of the last call (note that not all calls will set this value).

Value Description
0 No error
EDOM Domain error (from math)
EILSEQ Encoding error (from character conversion)
ERANGE Range error (from math)

If you’re doing a number of math functions, you might come across EDOM or ERANGE.

With multibyte/wide character conversion functions, you might see EILSEQ.

And your system might define any other number of values that errno could be set to, all of which will begin with the letter E.

Fun Fact: you can use EDOM, EILSEQ, and ERANGE with preprocessor directives such as #ifdef. But, frankly, I’m not sure why you’d do that other than to test their existence.

Example

The following prints an error message, since passing 2.0 to acos() is outside the function’s domain.

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

int main(void)
{
    double x;

    errno = 0;       // Make sure this is clear before the call

    x = acos(2.0);   // Invalid argument to acos()

    if (errno == EDOM)
        perror("acos");
    else
        printf("Answer is %f\n", x);

    return 0;
}

Output:

acos: Numerical argument out of domain

The following prints an error message (on my system), since passing 1e+30 to exp() produces a result that’s outside the range of a double.

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

int main(void)
{
    double x;

    errno = 0;       // Make sure this is clear before the call

    x = exp(1e+30);  // Pass in some too-huge number

    if (errno == ERANGE)
        perror("exp");
    else
        printf("Answer is %f\n", x);

    return 0;
}

Output:

exp: Numerical result out of range

This example tries to convert an invalid character into a wide character, failing. This sets errno to EILSEQ. We then use perror() to print an error message.

#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <errno.h>
#include <locale.h>

int main(void)
{
    setlocale(LC_ALL, "");

    char *bad_str = "\xff";  // Probably invalid char in this locale
    wchar_t wc;
    size_t result;
    mbstate_t ps;

    memset(&ps, 0, sizeof ps);

    result = mbrtowc(&wc, bad_str, 1, &ps);

    if (result == (size_t)(-1))
        perror("mbrtowc");  // mbrtowc: Illegal byte sequence
    else
        printf("Converted to L'%lc'\n", wc);

    return 0;
}

Output:

mbrtowc: Invalid or incomplete multibyte or wide character

See Also

perror(), mbrtoc16(), c16rtomb(), mbrtoc32(), c32rtomb(), fgetwc(), fputwc(), mbrtowc(), wcrtomb(), mbsrtowcs(), wcsrtombs(), <math.h>,


Prev | Contents | Next