1

I have this sample code where I pass the number of parameters in count followed by different type arguments.

struct my_struct;

my_func(int count, char* input_1, my_struct input_2, my_struct input_3);
my_func(int count, char* input_1, my_struct input_2);

How can I retrieve arguments? I Know using va_arg gives the argument for primary data types, but structs are not accepting.

harry
  • 970
  • 6
  • 25
  • 3
    "not accepting" what does it mean? Are you getting compilation errors? You should include them in your question. Make sure you have a [mcve]. – n. m. could be an AI Jul 13 '21 at 07:27
  • 1
    The example code you have posted are overloaded function prototypes not variadic functions. C does not support function overloading. Posting valid code, or code that reproduces the error you are seeing will make it much clearer what it is you are trying to do. – Clifford Jul 13 '21 at 07:48
  • Thanks for all the suggestions, I'll keep this in mind. It is indeed a duplicate as suggested by @Jabberwocky. Thanks for pointing it out. – harry Jul 13 '21 at 07:50
  • Except the behaviour of the one answer in the "duplicate" is undefined behaviour and not portable. https://stackoverflow.com/questions/10083844/passing-non-pod-type-to-variadic-function-is-undefined-behavior. Moreover with respect to the "suggestions", you should not simply _"keep this in mind"_; you should edit the question to correct its deficiencies. – Clifford Jul 13 '21 at 08:05
  • When all the variadic arguments are of the same type as appears to be the case here using a variadic function is an unnecessary complication. You could simply pass an array of structures to a regular function. – Clifford Jul 13 '21 at 08:14

2 Answers2

2

Passing a non-POD type as a variadic parameter is non-portable. I believe it will work (with warnings) in MSVC, while clang will outright refuse to compile it. In other cases it may compile (hopefully with warnings), but not execute in the way you might expect.

You can instead pass the variadic parameters as pointers then in the function:

// Get copy
my_struct input = *va_arg( vl, my_struct* ) ;

or

// Get reference
my_struct* input = va_arg( vl, my_struct* ) ;

The call might then look like:

my_struct a ;
my_struct b ;
...
my_func( 2, str, &a, &b ) ;
Clifford
  • 88,407
  • 13
  • 85
  • 165
0

Instead of passing the structs by-value, pass pointers to them.

Example:

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

typedef struct {
    char x;
} my_struct;

void my_func(char* input, ...) {
    va_list ap;
    va_start(ap, input);

    for(; *input; ++input) {
        my_struct* ptr = va_arg(ap, my_struct*); // get the pointer
        ptr->x = *input;                         // use it
    }

    va_end(ap);
}

int main() {
    my_struct a;
    my_struct b;

    my_func("a", &a);            // my_struct* 
    
    printf("%c\n", a.x);         // prints a

    my_func("xy", &a, &b);       // two my_struct*
    
    printf("%c %c\n", a.x, b.x); // prints x y
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108