2

Kindly let me know If there is way where I could use variable arguments inside a macro function and make the below macro code working.

To put it other way, Is there any way where I could use local variables in va_start.

typedef struct
{
    char *p1;
    char *p2;
    char *p3;
}Pointers;

#define NULLCHECK_VR(num, ...)                          \
        {                                               \
            va_list valist;                             \
            int     v_index;                            \
                                                        \
            va_start(valist, num);                      \
                                                        \
            for( v_index=0; v_index < num; v_index++)   \
            {                                           \
                if( NULL == va_arg(valist, void *))     \
                {                                       \
                    printf("NULL \n");                  \
                }                                       \
                else                                    \
                {                                       \
                    printf("NOT NULL \n");              \
                }                                       \
            }                                           \
                                                        \
            va_end(valist);                             \
        }

int main(void)
{
    Pointers ptr;

    memset(&ptr, 0, sizeof(Pointers));

    NULLCHECK_VR(3, ptr.p1, ptr.p2, ptr.p3)

    return (0);
}
4
  • 7
    C or C++? C++ has variadic template to resolve your issue. Commented Jan 14, 2020 at 10:09
  • 1
    MACRO is not function (but text replacement). so va_start(valist, num); is wrong as it applies to .. main. Commented Jan 14, 2020 at 10:10
  • You're mixing C-style variadic functions with variadic macros when you could be using a variadic template (if you're using C++ which I'm not sure you are). Commented Jan 14, 2020 at 10:11
  • Remove the #define and you will be fine Commented Jan 14, 2020 at 10:15

2 Answers 2

6

You might use regular function:

void NULLCHECK_VR(int num, ...)
{
    va_list valist;
    int     v_index;

    va_start(valist, num);

    for( v_index=0; v_index < num; v_index++)
    {
        if( NULL == va_arg(valist, void *))
        {
            printf("NULL\n");
        }
        else
        {
            printf("NOT NULL\n");
        }
    }

    va_end(valist);
}

or in C++ (17)

template <typename Ts>
void NULLCHECK_VR(const Ts*... ptrs)
{
    ((std::cout << (ptrs == nullptr ? "NULL\n" : "NOT NULL\n")), ...);
}
Sign up to request clarification or add additional context in comments.

Comments

2

You cannot use a va_list to access local variables. The va_start, va_copy and va_end macros are only for handling variadic function arguments. A macro is not a function.

For C variadic macros, the __VA_ARGS__ identifier in the macro replacement text will expand to the variadic arguments, so a possible implementation of your NULLCHECK_VR macro is as follows:

#define NULLCHECK_VR(num, ...)                          \
    do {                                                \
        void *_ptrs[] = { __VA_ARGS__ };                \
        int _num = (num);                               \
        int v_index;                                    \
                                                        \
        for (v_index = 0; v_index < _num; v_index++)    \
        {                                               \
            if (NULL == _ptrs[v_index])                 \
            {                                           \
                printf("NULL \n");                      \
            }                                           \
            else                                        \
            {                                           \
                printf("NOT NULL \n");                  \
            }                                           \
        }                                               \
    } while (0)

Here, __VA_ARGS__ has been used to initialize the local _ptrs array.

(I added local variable _num to avoid expanding the num parameter multiple times, and I used the do while (0) idiom to turn the block into a statement.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.