The snprintf() Function

Another non-standard library function is snprintf(). Like the strlcpy() and strlcat() functions shown in previous Lessons, snprintf() is safer than its standard Library counterpart, sprintf().

The sprintf() function is part of the family of printf() functions, each of which formats output. Here is its man page format:

int sprintf(char * restrict str, const char * restrict format, ...);

The function’s first argument is a buffer into which the formatted output is placed. No bounds-checking is performed, so the buffer can overflow, as the following code demonstrates:

#include <stdio.h>

int main()
{
    char buffer[12];
    int r;

    r = sprintf(buffer,"The total is %d\n",5+8);

    puts(buffer);
    printf("%d characters stored\n",r);

    return(0);
}

This code saves the sprintf() function’s return value. As with printf(), this value is equal to the characters output, or negative for an error. Here’s a sample run under Ubuntu Linux:

The total is 13

16 characters stored

The output on my Macintosh is far more telling:

Illegal instruction: 4

Even when the program doesn’t crash, you can see that 16 characters were stored in a 12 character buffer. The snprintf() function prevents this overflow from occurring. Here is its man page format:

int snprintf(char * restrict str, size_t size, const char * restrict format, ...);

As with sprintf(), the first argument is a buffer into which the formatted output is stored. A new second argument sets the buffer’s size. This size value caps the string at n-1 characters (one for the null character), preventing overflow. Here is the snprintf() version of the sample code:

#include <stdio.h>

int main()
{
    char buffer[12];
    int r;

    r = snprintf(buffer,12,"The total is %d\n",5+8);

    puts(buffer);
    printf("%d characters stored\n",r);

    return(0);
}

And sample output:

The total i
16 characters stored

The output is capped at 12 bytes; 11 for the string and one for the null character.

The return value, 16, is the same as for the sprintf() function. The logic here is that the return value can be compared with the function’s second argument to determine whether overflow would have occurred.

Coding my own snprintf() function would be truly complex. Not only must I emulate its behavior, but I must also reverse engineer the printf() function; as a standard I/O function, I couldn’t include its definition in stdio.h, which truly complicates matters.

Next week, I explore another interesting variation on the printf() function, asprintf().

Leave a Reply