Macros with a variable number of arguments

Macros with a variable number of arguments

Hi,

I am using version 7.0 of the Intel compiler for Linux (non-commercial) and I am having some trouble defining a macro with a variable number of arguments. As mentioned in the User's Guide of the compiler, it supports this functionality in the same way as gcc 3.1 does (see page 178 of c_ug_lnx.pdf that comes with the compiler).

The definition I use is as follows:

#define DBG(_msg_debug_level, _format_str, ...)
if (_msg_debug_level < debug_level) {
printf("%s: "_format_str, __func__,##__VA_ARGS__);
}

This prints the function name, followed by a semicolon, and then the rest of the message I define. This definiton has no problem with gcc. It also has no problem with icc, when I provide at least one OPTIONAL argument. But when I use icc and the optional argument list is blank I get an error:

Test.c(27): error: expected an expression
DBG(DBG_FATAL_ERROR, "My message
");
^

(There is no other argument after "My message
", which corresponds to _format_str in the definition)

It seems that the comma before ## is the problem, as it is left after preprocessing even when the list of optional arguments is blank. I also tried to delete ## but the same problem occured.

This is of course not a crucial problem and it is also not defined to work in ISO C99, but it makes this extension not compatible with gcc, in contrast to what is stated in the manual.

Is this a known issue and is there a work-around for this?

Thank you in advance for any help,

Ioannis

9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi Ioannis,

Here is a workaround -

for this macro defn -

#define DBG(_msg_debug_level, _format_str, ...)
if (_msg_debug_level < debug_level) {
printf("%s: "_format_str, __func__,##__VA_ARGS__);
}

Give a blank space between __func__ and , i.e. printf
statement should be this -

printf("%s: "_format_str, __func__ ,##__VA_ARGS__);

This works fine with both icc and gcc.

There could be a issue with Intel compiler preprocessor.
You may write to Tech support.

Regards,
CP
Persistent Systems

Thank you!

It works as expected now. But I am a little bit confused about the Tech support. I cannot find the link that I have to follow. I don't think that it is the one at the beginning of each page in the forum, as this leads to FAQs and there is no information how to submit a question.
Moreover, isn't it necessary to be a registered user of the compiler to have access to something like this? Anyway, I would like to submit a bug(?) report, as I really like the compiler and I would be very happy to see it getting better, but I can't find out how to do it!

Ioannis

Ioannis,
Welcome!

Please choose "Premier Support" on the left hand side from the "User Resources" link above (http://intel.com/software/products/compilers).

Cheers,
Ganesh

I am converting a solution from VS 2005 to icc (11.0 for Windows). The workaround presented for Linux icc above does not work for Windows.

The macro is defined as below (note that I have added spaces around each comma):

#define dd_err_fmt(errnum, fmt, ...)
dd_err_fmt_intern(__FILE__ , __FUNCTION__ , __LINE__ , errnum , fmt , ##__VA_ARGS__)

The macro is invoked as below:
dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);

The error reported is:
1>.main.c(43): error: expected a ")"
1> dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);

I have tried a collection of /Qstd settings (would like to use c99) to no avail. For completeness I have pasted my minimal demonstration code:
--------------------------------------------
#include
#include
#include

void dd_err_fmt_intern(const char *file,
const char *func,
const int lineno,
const int errnum,
const char *fmt,
...)
{
va_list args;
char buffer[1024];

va_start(args, fmt);
vsnprintf(buffer, 1024, fmt, args);
va_end(args);

printf(buffer);

}

#define dd_err_fmt(errnum, fmt, ...)
dd_err_fmt_intern(__FILE__ , __FUNCTION__ , __LINE__ , errnum , fmt , ##__VA_ARGS__)

int main()
{
char local_str[]="local string";
char nfs_str[]="nfs_str";
int dd_errnum = 42;

dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);
}
----------------------------------------------
Any advice would be most appreciated.

Thanks,

Howard

Quoting - hcunningham

I am converting a solution from VS 2005 to icc (11.0 for Windows). The workaround presented for Linux icc above does not work for Windows.

The macro is defined as below (note that I have added spaces around each comma):

#define dd_err_fmt(errnum, fmt, ...)
dd_err_fmt_intern(__FILE__ , __FUNCTION__ , __LINE__ , errnum , fmt , ##__VA_ARGS__)

The macro is invoked as below:
dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);

The error reported is:
1>.main.c(43): error: expected a ")"
1> dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);

I have tried a collection of /Qstd settings (would like to use c99) to no avail. For completeness I have pasted my minimal demonstration code:
--------------------------------------------
#include
#include
#include

void dd_err_fmt_intern(const char *file,
const char *func,
const int lineno,
const int errnum,
const char *fmt,
...)
{
va_list args;
char buffer[1024];

va_start(args, fmt);
vsnprintf(buffer, 1024, fmt, args);
va_end(args);

printf(buffer);

}

#define dd_err_fmt(errnum, fmt, ...)
dd_err_fmt_intern(__FILE__ , __FUNCTION__ , __LINE__ , errnum , fmt , ##__VA_ARGS__)

int main()
{
char local_str[]="local string";
char nfs_str[]="nfs_str";
int dd_errnum = 42;

dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);
}
----------------------------------------------
Any advice would be most appreciated.

Thanks,

Howard

Hi, if we replace the dd_err_fmt(dd_errnum, "%s (nfs: %s)", local_str, nfs_str);
with
dd_err_fmt(dd_errnum , "%s" , "%s", local_str, nfs_str);

It works without any error.

Though the former should also work, since it works with microsoft compiler.

Seems to be a bug.

There's no really needed to submit another issue to Premier Support. But it's ok to submit.
Each posting has an unique ID assosicated. so we can track the bug report based on this ID.

I will create a bug report about the Linux issue and the Window issue.

Thanks all.
Jennifer

Quoting - hcunningham

#define dd_err_fmt(errnum, fmt, ...)
dd_err_fmt_intern(__FILE__ , __FUNCTION__ , __LINE__ , errnum , fmt , ##__VA_ARGS__)

About this Windows icl issue, just remove the "##" from the define. All should be fine. So I'll submit a bug report about it. cl can compile fine.

Jennifer

This issue has been fixed in our 11.1 branch line. The 11.1 will be released in mid this year.

Thanks for posting.
Jennifer

Leave a Comment

Please sign in to add a comment. Not a member? Join today