Thread: Help with Variadic Macro Function

  1. #1
    Registered User
    Join Date
    Sep 2012
    Posts
    28

    Help with Variadic Macro Function

    OK, so what I'm doing right now is creating a function that callocs (I prefer this to malloc) and returns a string, and it will work similar to printf, I'm calling the function alloCpy(), the idea is this:
    I have several values that I need in a malloced string, so I call
    Code:
    myAllocedString = alloCpy("Value 1 is %s, value 2 is %s, and value 3 is %d", str1, str2, num);
    To do this I'm using the Variadic Macro, the reason I'm not just using a Variadic Function such as this:
    Code:
    char* alloCpy(char *format, ...) {}
    is because I need to append NULL to the end for the sake of looping through arguments, and I'm understanding it thusfar, but I have a few issues, first of all, I tried defining the Macro in a header file, but when I try to call it I get the error "Undefined reference to alloCpy". Also, to loop through arguments to get string lengths I'm using va_arg(args, char*) which requires all the arguments to be of type char*. Here is my code:
    myheader.h:
    Code:
    #define alloCpy(format, ...) _alloCpy(format, ##__VA_ARGS__, NULL);
    char* _alloCpy(char *format, ...);
    mycfile.c:
    Code:
    char* _alloCpy(char *format, ...) {
        va_list args;
        va_start(args, format);
        int args_len = 0;
    
    
        char *arg;
        for(arg = va_arg(args, char*); arg != NULL; arg = va_arg(args, char*))
            args_len += strlen(arg);
    
    
        // Allocated memory will have extra padding because of formatting chars (%s, %d, etc.)
        char *dest = calloc(strlen(format) + args_len + 1, sizeof(char));
        vsprintf(dest, format, args);
    
    
        return dest;
    }
    So, how can I do this to, first of all, make my macro function accessible from other files importing myheader.h, and second, how can I make it accept any type of argument like printf, so that my example above would work?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    Code:
    char* alloCpy(char *format, ...) {
        va_list args, ap2;
        va_start(args, format);
        va_copy(ap2,args);
        int args_len = vsnprintf(NULL,0,format,args);
        char *dest = calloc(args_len+1, sizeof(char));
        vsprintf(dest, format, ap2);
        va_end(ap2);
        va_end(args);
        return dest;
    }
    Things to note.
    1. vsnprintf with NULL,0 will count how many characters you would have needed.
    2. Since varargs are parsed twice, you need to make a copy using va_copy.
    3. Each copy of args needs a va_end() matching it.
    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.

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You don't need the NULL at the end of your arguments since your format string has the information about how many args there are. That's how printf does it.

    External identifiers starting with an underscore are reserved for the implementation.
    Reserved Names - The GNU C Library

    If this is just an exercise, then to do it like printf does you need to go through the string and deal with each format you find, perhaps with a switch on the type. You'll probably have to go through the whole thing twice to determine the total length first, although I can imagine alternatives.

    If this isn't just an exercise, then Salem has demonstrated the proper way to do it. An alternative to va_copy would be to use va_end and then va_start again on a single va_list variable.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #4
    Registered User
    Join Date
    Sep 2012
    Posts
    28
    @Salem
    That's exactly what I needed! Thanks, I don't know why I didn't think of that, I was totally over complicating it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 07-18-2012, 08:53 PM
  2. Overloading a variadic macro
    By Richardcavell in forum C Programming
    Replies: 6
    Last Post: 03-14-2011, 06:24 PM
  3. Variadic function
    By Richardcavell in forum C Programming
    Replies: 17
    Last Post: 03-01-2011, 01:34 AM
  4. macro function
    By freeindy in forum C Programming
    Replies: 6
    Last Post: 11-08-2007, 05:04 AM
  5. macro function
    By bradleyd in forum C Programming
    Replies: 8
    Last Post: 05-21-2007, 05:18 PM

Tags for this Thread