Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7744073
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T09:41:06+00:00 2026-06-01T09:41:06+00:00

I have some code that converts variadic parameters into a va_list , then passes

  • 0

I have some code that converts variadic parameters into a va_list, then passes the list on to a function that then calls vsnprintf. This works fine on Windows and OS X, but it is failing with odd results on Linux.

In the following code sample:

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

char *myPrintfInner(const char *message, va_list params)
{
    va_list *original = &params;
    size_t length = vsnprintf(NULL, 0, message, *original);
    char *final = (char *) malloc((length + 1) * sizeof(char));
    int result = vsnprintf(final, length + 1, message, params);

    printf("vsnprintf result: %d\r\n", result);
    printf("%s\r\n", final);

    return final;
}

char *myPrintf(const char *message, ...)
{
    va_list va_args;
    va_start(va_args, message);

    size_t length = vsnprintf(NULL, 0, message, va_args);
    char *final = (char *) malloc((length + 1) * sizeof(char));
    int result = vsnprintf(final, length + 1, message, va_args);

    printf("vsnprintf result: %d\r\n", result);
    printf("%s\r\n", final);

    va_end(va_args);

    return final;
}

int main(int argc, char **argv)
{
    char *test = myPrintf("This is a %s.", "test");
    char *actual = "This is a test.";
    int result = strcmp(test, actual);

    if (result != 0)
    {
        printf("%d: Test failure!\r\n", result);
    }
    else
    {
        printf("Test succeeded.\r\n");
    }

    return 0;
}

The output of second vsnprintf call is 17, and the result of strcmp is 31; but I don’t get why vsnprintf would return 17 seeing as This is a test. is 15 characters, add the NULL and you get 16.

Related threads that I’ve seen but do not address the topic:

  • Pass va_list or pointer to va_list?
  • Passing one va_list as a parameter to another

With @Mat’s answer (I am reusing the va_list object, which is not allowed), this comes squarely around to the first related thread I linked to. So I attempted this code instead:

char *myPrintfInner(const char *message, va_list params)
{
    va_list *original = &params;
    size_t length = vsnprintf(NULL, 0, message, params);
    char *final = (char *) malloc((length + 1) * sizeof(char));
    int result = vsnprintf(final, length + 1, message, *original);

    printf("vsnprintf result: %d\r\n", result);
    printf("%s\r\n", final);

    return final;
}

Which, per the C99 spec (footnote in Section 7.15), should work:

It is permitted to create a pointer to a va_list and pass that pointer
to another function, in which case the original function may make
further use of the original list after the other function returns.

But my compiler (gcc 4.4.5 in C99 mode) gives me this error regarding the first line of myPrintfInner:

test.c: In function ‘myPrintfInner’: 
test.c:8: warning: initialization from incompatible pointer type

And the resulting binary produces the exact same effect as the first time around.


Found this: Is GCC mishandling a pointer to a va_list passed to a function?

The suggested workaround (which wasn’t guaranteed to work, but did in practice) is to use arg_copy first:

char *myPrintfInner(const char *message, va_list params)
{
    va_list args_copy;
    va_copy(args_copy, params);

    size_t length = vsnprintf(NULL, 0, message, params);
    char *final = (char *) malloc((length + 1) * sizeof(char));
    int result = vsnprintf(final, length + 1, message, args_copy);

    printf("vsnprintf result: %d\r\n", result);
    printf("%s\r\n", final);

    return final;
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T09:41:07+00:00Added an answer on June 1, 2026 at 9:41 am

    As Mat notes, the problem is that you’re reusing the va_list. If you don’t want to restructure your code as he suggests, you can use the C99 va_copy() macro, like this:

    char *myPrintfInner(const char *message, va_list params)
    {
        va_list copy;
    
        va_copy(copy, params);
        size_t length = vsnprintf(NULL, 0, message, copy);
        va_end(copy);
    
        char *final = (char *) malloc((length + 1) * sizeof(char));
        int result = vsnprintf(final, length + 1, message, params);
    
        printf("vsnprintf result: %d\r\n", result);
        printf("%s\r\n", final);
    
        return final;
    }
    

    On compilers that don’t support C99, you may be able use __va_copy() instead or define your own va_copy() implementation (which will be non-portable, but you can always use compiler / platform sniffing in a header file if you really need to). But really, it’s been 13 years — any decent compiler should support C99 these days, at least if you give it the right options (-std=c99 for GCC).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have placed together some code which converts strings into data, and then places
I have some code that gives a user id to a utility that then
I have some code that simply accesses a datetime field so activerecord converts it
I have the following code that converts my twitter account rss feed into a
I've got some Python code that runs through a list of strings and converts
In code below is function that converts slider class into slider control. It has
I have some JQuery code that converts all HTML elements of a specific class
I have some c(++) code that uses sprintf to convert a uint_64 to a
I have some code that creates a new event source: EventLog.CreateEventSource(Source, LogName); I know
I have some code that uses the shared gateway pattern to implement an inversion

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.