Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the size of varargs in C?

I am trying to convert some Java code into C. The Java code goes like this:

public static int minimum( int... minimum ) {

    assert( minimum.length > 0 );

    if ( minimum.length > 0 )
     .... // some code that i am able to translate to C without any hassle
}

Now I understand how to have varargs in C by using the stdarg.h header and using the macros provided. However I am stuck doing the minimum.length part.

I have tried strlen but the terminal is giving me an incompatible integer to pointer conversion warning. Is there any way in C where I can replicate the same thing that Java does?

like image 997
Saad Avatar asked Dec 24 '22 20:12

Saad


2 Answers

Not directly, as pointed out by @MichaelBurr, you need to pass the number of elements or use a sentinel.

An indirect way to do this is using compound literals:

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

#define minimum(...) fnminimum(sizeof((int []) {__VA_ARGS__}) / sizeof(int), __VA_ARGS__)

static int fnminimum(int n, ...)
{
    int num, min = INT_MAX;
    va_list ap;

    va_start(ap, n);
    while (n--) {
        num = va_arg(ap, int);
        if (num < min) {
            min = num;
        }
    }
    va_end(ap);
    return min;
}

int main(void)
{
    int a = 1;

    printf("%d\n", minimum(2, 30, 7, a++, 4));
    return 0;
}

Another (ugly) method using NARGS macros (limited to N args):

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

#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)

#define minimum(...) fnminimum(NARGS(__VA_ARGS__), __VA_ARGS__)

static int fnminimum(int n, ...)
{
    int num, min = INT_MAX;
    va_list ap;

    va_start(ap, n);
    while (n--) {
        num = va_arg(ap, int);
        if (num < min) {
            min = num;
        }
    }
    va_end(ap);
    return min;
}

int main(void)
{
    printf("%d\n", minimum(2, 30, 7, 1, 4));
    return 0;
}

Output:

1
like image 82
David Ranieri Avatar answered Jan 05 '23 00:01

David Ranieri


There is no built-in way to get the number of vararg arguments passed in C.

You need to do one of the following:

  • pass in a count explicitly,
  • pass in a count implicitly (as printf() does via the number of conversion specifiers)
  • or use a sentinel value (such as NULL or 0) to indicate the end of the vararg list

I have seen schemes that use macros and the __VA_ARGS__ identifier to automatically place a sentinel at the end of the varargs list when calling a function.

like image 34
Michael Burr Avatar answered Jan 05 '23 00:01

Michael Burr