Thread: va_list confusion

  1. #1
    Registered User
    Join Date
    Mar 2022
    Posts
    7

    Arrow va_list confusion

    Hey there, hope you're having an awesome weekend!

    So............... yeah, my brain hurts.

    I have two functions that work with va_lists: one ("Say") that uses vsnprintf. It works in isolation. There other ("Write") calls Say and also the ncurses function "vw_printw" 9like a printf except that it also takes a va_list and works in the "ncurses" library). The ncurses part, obviously, also works in isolation. But when I try to put them both in the same function, "weird happens." For some reason, instead of putting the data (a const char * in my tests) into the string, it inserts the text "^P". I'm guessing the problem is the fact that I don't really know how va_lists work under the hood. There's probably some pointer moving somewhere, or something that got NULLed somehow... lol idk...

    Anyway, here's the code:

    Code:
    void Say(bool rightNow, const char *format, ...) {
        /* Declare variables */
        va_list args;
        char buffer[256];
        
        /* Pass the variable arguments into our buffer */
        va_start(args, format);
        vsnprintf(buffer, 256, format, args);
        printw("Saying: \"%s\n\"", buffer);
        va_end (args);
        
        /* Stop speech if theuser wants this text spoken immediately */
        if (rightNow) espeak_Cancel();
        
        /* Tell eSpeak to speak our buffer */
        espeak_Synth((const char *)buffer, strlen(buffer) + 1, 0, POS_SENTENCE, 0, espeakCHARS_AUTO, NULL, NULL);
    }
    
    void Write(bool speakImmediately, const char * format, ...) {
        va_list list1, list2;
        
        va_start(list1, format);
        vw_printw(stdscr, format, list1);
        va_end(list1);
        
        // Tried a second va_list... no dice
        va_start(list2, format);
        Say(speakImmediately, (char *)format, list2);
        va_end(list2);
    }
    
    // Then the code that calls it, "Say" by itself seems to work.
    Say(false, (char *)"What the %s?", "puck");
    // Obviously, printw by itself works as well.
    // But with this, I get "What the ^P?"
    Write(false, "What the %s?", "puck");
    At this point I'm considering abandoning my write function completely and just always calling speak and printw, which is kind of a setback (I'll have to add a lot more variables so I can pass them in to both functions etc.) but I can't find anything on the interwebz that would provide a logical explanation. Maybe passing a va_list to a function that uses a va_list is invalid somehow? Anyway I'm compiling this with GCC on 64-bit Linux Mint, using -Wall, and I'm not getting any warnings.

    Thanks in advance.

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,632
    Code:
    void Say2(bool rightNow, const char *format, va_list args) {
        char buffer[256];
        vsnprintf(buffer, 256, format, args);
        printw("Saying: \"%s\n\"", buffer);
        if (rightNow) espeak_Cancel();
        espeak_Synth((const char *)buffer, strlen(buffer) + 1, 0,
             POS_SENTENCE, 0, espeakCHARS_AUTO, NULL, NULL);
    }
     
    void Say(bool rightNow, const char *format, ...) {
        va_list args;
        va_start(args, format);
        Say2(rightNow, format, args);
        va_end(args);
    }
     
    void Write(bool speakImmediately, const char *format, ...) {
        va_list list1, list2;
        va_start(list1, format);
        vw_printw(stdscr, format, list1);
        va_end(list1);
        va_start(list2, format);
        Say2(speakImmediately, format, list2);
        va_end(list2);
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Mar 2022
    Posts
    7
    Hahahahahaha wow, so simple, and yet so genius! Thank you so much! Man, why didn't I think of that?

    So I get how this works - it's pretty obvious - but what I don't understand is why it was necessary. I'd be interested in any info you may have on the subject, but it's just out of curiosity now - I got some more hacking to do on this project now that I'm past this stupid bug!

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    The basic problem you had was that you can't pass ... directly onto another function that also uses ...

    You have to use a va_list as john.c showed.

    > Anyway I'm compiling this with GCC on 64-bit Linux Mint, using -Wall, and I'm not getting any warnings.
    Yeah, ... does that.
    Parameters that match against ... get no type checking, no automatic promotion (or demotion) or anything.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Oct 2019
    Posts
    82
    I was under the impression that you could use _VA_ARGS__ in this case

    But

    It seem it can only be used in macros.

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,632
    If I understand your question you are asking why you can't pass a va_list to a ... and have it "unpack" into separate variables again like the ones that were used to call the current function. All I can say is it simply doesn't work like that. It would be impossible for it to automatically unpack into separate variables correctly since it's up to you to tell it the types with va_arg. It's a very low-level and error-prone mechanism that exists primarily to implement the printf and scanf family of functions.
    A little inaccuracy saves tons of explanation. - H.H. Munro

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. va_list
    By seaweedA in forum C Programming
    Replies: 2
    Last Post: 04-30-2007, 10:39 AM
  2. va_list issues
    By LPP in forum C++ Programming
    Replies: 10
    Last Post: 10-20-2006, 06:29 PM
  3. va_list on win32
    By l2u in forum C++ Programming
    Replies: 1
    Last Post: 06-03-2006, 12:18 PM
  4. FreeBSD 5.1, gcc 3.3.3 and va_list
    By Longie in forum Linux Programming
    Replies: 5
    Last Post: 07-07-2004, 07:27 PM
  5. va_list 's
    By Patrick in forum C++ Programming
    Replies: 4
    Last Post: 10-31-2002, 05:31 PM

Tags for this Thread