-1

So I am trying to learn C and I stumble on stdarg and ellipses (...). I write the example:

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

int please_work(int num_args, ...);

int main(void){
  please_work(10, 1, 12, 345, 231431, 334341);
  return 0;
}

int please_work(int num_args, ...){
  va_list args;
  va_start(args, num_args);
  for (int i = 0; i < num_args; i++){
    int x = va_arg(args, int);
    printf("x: %d\n", x);
  }
  
  va_end(args);
  return 0;
}

But except of printing:

x: 1
x: 12
x: 345
x: 231431
x: 334341

It prints those values but with additional garbage values which end up printing like this:

x: 1
x: 12
x: 345
x: 231431
x: 334341
x: 4198720
x: 1880629838
x: 1883666304
x: 4198720
x: 4194368

I have tried for like an hour, but nothing

dbush
  • 205,898
  • 23
  • 218
  • 273
Reck
  • 11
  • 4
  • 8
    You're telling the function to expect 10 arguments. – dbush Mar 29 '23 at 18:21
  • 1
    The first argument is supposed to be the number of additional arguments after it. So if you pass 5 numbers that should be printed, the first argument should be `5`, not `10`. – Barmar Mar 29 '23 at 18:24
  • I see it, but how can i make it so that it expects an undefined amount of arguments, that resize? So for example, if i write please_work(2, 3, 4, 5), it will scale to 3 arguments except of 2? – Reck Mar 29 '23 at 18:24
  • You don't, at least not without ugly macro trickery. – dbush Mar 29 '23 at 18:25
  • Could you show me an example of "ugly macro trickery"? – Reck Mar 29 '23 at 18:26
  • 3
    You want to pass the ***wrong*** number of arguments, yet still have the function know what the proper number is, despite what you passed? You should just pass the correct value. – abelenky Mar 29 '23 at 18:26
  • Such trickery has its own problem that would trip up beginners. Best to be clear and explicit about what you're passing. – dbush Mar 29 '23 at 18:36
  • 2
    Here's an example of macro trickery: https://stackoverflow.com/a/2308651/5264491 . It could be used by defining `PLEASE_WORK` like this: `#define PLEASE_WORK(...) please_work(PP_NARG(__VA_ARGS__), __VA_ARGS__)`. Then `PLEASE_WORK(10, 11, 12, 13)` would expand to `please_work(4, 10, 11, 12, 13)`. The linked-to `PP_NARG()` macro can count up to 64 arguments but needs at least 1 argument. – Ian Abbott Mar 29 '23 at 18:55

2 Answers2

1

If you are willing to use a sentinel value to indicate the end of the arguments, the following may provide an example.

#include <stdio.h>
#include <stdarg.h>
#include <limits.h> // for 'INT_MIN'

// a function defined ahead of its use acts as its own prototype
int please_work( int val, ... ) {
    va_list args;
    va_start( args, val );
    for( ; val != INT_MIN; val = va_arg(args, int) )
        printf( "%d ", val );
    putchar( '\n' );

    va_end( args );

    return 0;
}

int main( void ) {
    please_work( 10, 1, 12, 345, 231431, 334341, INT_MIN );

    return 0;
}
10 1 12 345 231431 334341

Of course there are better ways to express a collection of constants (array?). Remember that the function call, with its list of parameters, will only be interpreted at compile time. While the constants could be replaced by variables, their number is fixed.

Fe2O3
  • 6,077
  • 2
  • 4
  • 20
0

The fist argument is the number of variable arguments you are going to provide.

  • changed 10 to 5 from the given code
  • added two other test cases
#include <stdio.h>
#include <stdarg.h>

int please_work(int num_args, ...);

int main(void){
  // first argument is 5, because 5 values are given
  please_work(5, 1, 12, 345, 231431, 334341);

  // Test some other cases
  printf("Zero vars:\n");
  please_work(0);

  printf("One var:\n");
  please_work(1, 44);

  return 0;
}

int please_work(int num_args, ...){
  va_list args;

  // Point to the last argument, before the variable list
  va_start(args, num_args);

  for (int i = 0; i < num_args; i++){
    int x = va_arg(args, int); // get argument
    printf("x: %d\n", x);
  }

  va_end(args);
  return 0;
}

Good Luck

S_IROTH
  • 210
  • 1
  • 5
  • Hint: In Linux and probably other alike systems, there is a specific man page for stdarg. "man stdarg", but also for "stdio" and more. .. – S_IROTH Mar 29 '23 at 21:54