Reputation: 23
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
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