Marcus Paulo Botelho
Marcus Paulo Botelho

Reputation: 23

Difference between variadic parameters with and without parentheses

Why using parentheses in the first code works and the second doesn't?

In the first code I'm using only variadic parameter with parentheses and the seconde one have a Integer parameter with a variadic, if I use parentheses when I call the function it won't work.

#include <bits/stdc++.h>

void func( char* szFormat, ... );

#define M1(a)  M2(a)
#define M2(b) func b

int main()
{
    M1(("Hello %s %d\n", "world",2015)); // this works
    return 0;
}

void func( char* szFormat, ... )
{
    char      trace_str[1000];
    va_list   arg_list;
    std::string str;

    va_start(arg_list, szFormat);
    vsprintf(trace_str, szFormat, arg_list);
    va_end(arg_list);

    str += trace_str;
    std::cout << str << std::endl;
}

This code below doesn't work using parentheses.

#include <bits/stdc++.h>

void func( int year, char* szFormat, ... );

#define M1(a,...)  M2(a, __VA_ARGS__)
#define M2 func 

int main()
{
 // M1(2015, ("Hello %s", "world")); // this doesn't works
    M1(2015, "Hello %s", "world");   // this way works
    return 0;
}

void func(int year, char* szFormat, ... )
{
    char      trace_str[1000];
    va_list   arg_list;
    std::string str;


    va_start(arg_list, szFormat);
    vsprintf(trace_str, szFormat, arg_list);
    va_end(arg_list);

    str += trace_str;
    std::cout << str << " " << year << std::endl;

}

Thanks everyone!

Upvotes: 2

Views: 139

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 149125

It is enough to see preprocess output to understand that.

Input file:

void func( int year, char* szFormat, ... );

#define M1(a,...)  M2(a, __VA_ARGS__)
#define M2 func 

int main()
{
    M1(2015, ("Hello %s", "world")); // this doesn't works
    M1(2015, "Hello %s", "world");   // this way works
    return 0;
}

output of c++ -E foo.cpp:

# 1 "ess.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 155 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "ess.cpp" 2
void func( int year, char* szFormat, ... );




int main()
{
    func(2015, ("Hello %s", "world"));
    func(2015, "Hello %s", "world");
    return 0;
}

The relevant part is here:

    M1(2015, ("Hello %s", "world")); // this doesn't works
    M1(2015, "Hello %s", "world");   // this way works

    func(2015, "Hello %s", "world");
    func(2015, "Hello %s", "world");

The macro is only interpreted by the preprocessor. If you put two parentheses levels, you get one extra in the function call, and it does not give expected result. Here compiler will just see the comma operator in the inner bloc, would see a void evaluataion or "Hello %s" followed with "world" and it will end in func(2015, "world");. But func(2015, ("Hello %d", 12)); would end in func(2015, 10); with a syntax error no known conversion from 'int' to 'char *' for 2nd argument


In first code, you had #define M2(b) func b that removed one parentheses level, so

M1(("Hello %s %d\n", "world",2015));

was (correctly) preprocessed as

func ("Hello %s %d\n", "world",2015);

Upvotes: 2

Related Questions