ZetCode

C snprintf function

last modified April 6, 2025

String formatting is a core operation in C programming, enabling dynamic text creation. The snprintf function provides safe buffer handling by preventing overflow vulnerabilities common with sprintf. This tutorial explores snprintf's syntax, usage patterns, and practical applications. You'll learn to format strings securely while avoiding common pitfalls. Mastering snprintf is essential for writing robust C programs that handle text safely.

What Is snprintf?

The snprintf function formats and stores output in a buffer while respecting size limits. It takes a buffer, its maximum size, a format string, and optional arguments. Unlike sprintf, it prevents buffer overflow by truncating output if needed. It returns the number of characters that would have been written if space allowed. Always use snprintf instead of sprintf when security matters.

Basic snprintf Usage

This example demonstrates the fundamental usage of snprintf to format a simple string.

basic_snprintf.c
#include <stdio.h>

int main() {
    char buffer[50];
    int year = 2025;
    const char *language = "C programming";
    
    int result = snprintf(buffer, sizeof(buffer), 
                         "Welcome to %s in %d", language, year);
    
    if (result >= sizeof(buffer)) {
        printf("Warning: Output truncated (needed %d chars)\n", result);
    }
    
    printf("Formatted string: %s\n", buffer);
    return 0;
}

Here, snprintf formats a string into buffer with a maximum size of 50 bytes. The format specifiers %s and %d insert the string and integer values. The return value check detects potential truncation. This approach ensures safe string formatting regardless of input size.

Preventing Buffer Overflow

See how snprintf prevents buffer overflow compared to unsafe alternatives.

safety_comparison.c
#include <stdio.h>

int main() {
    char small_buffer[10];
    const char *long_text = "This text is definitely too long for the buffer";
    
    // Safe version with snprintf
    int safe_result = snprintf(small_buffer, sizeof(small_buffer), "%s", long_text);
    printf("Safe output: '%s' (truncated at %d chars)\n", small_buffer, safe_result);
    
    // Unsafe version (commented out - don't use in production)
    // sprintf(small_buffer, "%s", long_text); // Buffer overflow!
    // printf("Unsafe output: '%s'\n", small_buffer);
    
    return 0;
}

The safe snprintf version truncates output to fit the 10-byte buffer, while the commented sprintf would cause undefined behavior. The return value indicates the full length needed (45 chars), allowing detection of truncation. Always prefer snprintf when dealing with untrusted or variable-length input.

Building Paths Safely

Combine directory and filename components securely using snprintf.

path_building.c
#include <stdio.h>
#include <limits.h> // For PATH_MAX

int main() {
    char full_path[PATH_MAX];
    const char *dir = "/usr/local/share";
    const char *file = "config.txt";
    
    int needed = snprintf(full_path, sizeof(full_path), 
                         "%s/%s", dir, file);
    
    if (needed >= sizeof(full_path)) {
        fprintf(stderr, "Path too long (max %zu)\n", sizeof(full_path));
        return 1;
    }
    
    printf("Full path: %s\n", full_path);
    return 0;
}

This example constructs a filesystem path safely by using PATH_MAX for buffer size. The return value check ensures the path wasn't truncated. snprintf automatically handles the separator and concatenation safely. For path manipulation, always check length requirements to prevent security issues.

Formatting Numbers with Commas

Format large numbers with thousand separators using snprintf.

number_formatting.c
#include <stdio.h>
#include <locale.h>

int main() {
    setlocale(LC_NUMERIC, ""); // Enable locale-specific formatting
    
    char formatted[20];
    long population = 789654321;
    
    snprintf(formatted, sizeof(formatted), "%'ld", population);
    
    printf("World population: %s\n", formatted);
    return 0;
}

The %'ld format specifier adds locale-appropriate thousand separators. setlocale enables this feature system-wide. The buffer size (20) safely accommodates the formatted number. Note that locale support varies by system. This technique improves number readability in output.

Creating a Log Message

Build a timestamped log message with multiple variables safely.

log_message.c
#include <stdio.h>
#include <time.h>

int main() {
    char log_entry[256];
    time_t now = time(NULL);
    const char *user = "admin";
    int event_id = 42;
    
    strftime(log_entry, sizeof(log_entry), "[%Y-%m-%d %H:%M:%S] ", 
             localtime(&now));
             
    int used = strlen(log_entry);
    snprintf(log_entry + used, sizeof(log_entry) - used,
             "User '%s' triggered event %d", user, event_id);
    
    printf("Log entry: %s\n", log_entry);
    return 0;
}

This example combines strftime for timestamp formatting with snprintf for the message. The buffer space is carefully managed by tracking used space. The second snprintf writes after the timestamp without overflow risk. This pattern is ideal for building complex strings from multiple components.

Best Practices for Using snprintf

Source

C snprintf Documentation

This tutorial has demonstrated snprintf's role in safe string formatting through practical examples. By preventing buffer overflows and providing truncation detection, it's an essential tool for secure C programming.

Author

My name is Jan Bodnar, and I'm a dedicated programmer with a deep passion for coding. Since 2007, I've been sharing my expertise through over 1,400 articles and 8 e-books. With more than a decade of teaching experience, I strive to make programming accessible and engaging.

List C Standard Library.