Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

stdarg.h formating string via snprintf not working, arguments are ignored

In C (gcc, ubuntu 22.04) I’m trying to create formatted string using format string and … arguments, like a sprintf, but it would return the formatted string, e.g. char *s = myformat("Hello %s", name) but for some reason it is not working, as if the name was empty.

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

char* myformat(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    size_t len = snprintf(NULL, 0, fmt, args);
    if (len > 0) {
        char *s = (char*)malloc(len + 1);
        if (s) {
            printf("len=%ld\n", len); // prints len=11 which is "hello  zzz"+1
            snprintf(s, len + 1, fmt, args);
        } else {
            fprintf(stderr, "error: create_formated_string() failed to allocate %ld chars\n", len + 1);
            exit(1);
        }
        return s;
    }
    va_end(args);
    return NULL;
}

int main(void) {
    char *name = "John";
    char *s = myformat("Hello %s zzz", name);
    printf("s=%s\n", s);
    free(s);
    return 0;
}                              

It will print

s=Hello zzz

Instead of

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

s=Hello John zzz

I’m compiling using: "gcc test.c" on Ubuntu 22.04.

I tried using vsnprintf but it now prints random characters instead of name:

char* myformat(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    size_t len = vsnprintf(NULL, 0, fmt, args);
    char *s;
    if (len > 0) {
        s = (char*)malloc(len + 1);
        if (s) {
            printf("len=%ld\n", len); // prints len=11 which is "hello  zzz"+1
            vsnprintf(s, len + 1, fmt, args);
        } else {
            fprintf(stderr, "error: create_formated_string() failed to allocate %ld chars\n", len + 1);
            exit(1);
        }
    }
    va_end(args);
    return s;
}

int main(void) {
    char *name = "John";
    char *s = myformat("Hello %s zzz", name);
    printf("s=%s\n", s);
    free(s);
    return 0;
}   

        

>Solution :

It does not work like this. You need to use special functions which take va_list argument.

int vsnprintf (char * s, size_t n, const char * format, va_list arg );

But it will not work without some modifications. The fist call will modify args and you need to copy it.

char* myformat(const char *fmt, ...) {
    va_list args,copy;
    va_start(args, fmt);
    va_copy(copy, args);
    size_t len = vsnprintf(NULL, 0, fmt, args);
    if (len > 0) {
        char *s = malloc(len + 1);
        if (s) {
            printf("len=%ld\n", len); // prints len=11 which is "hello  zzz"+1
            vsnprintf(s, len + 1, fmt, copy);
        } else {
            fprintf(stderr, "error: create_formated_string() failed to allocate %zu chars\n", len + 1);
            exit(1);
        }
        return s;
    }
    va_end(args);
    va_end(copy);
    return NULL;
}

https://godbolt.org/z/qqsz89dvz

Also %ld is not correct to print size_t parameter. You need to use %zu format

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading