By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,411 Members | 1,037 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,411 IT Pros & Developers. It's quick & easy.

C preprocessor function macros with empty aguments

P: n/a
While trying to port some stuff from Unix to Windows, I encountered a
strange behaviour of function macros with empty arguments. Here is a small
snippet which illustrates the problem:

#include <iostream>
#include <string>
using namespace std;

#define B(X, Y) Y

int main()
{
string mystr (B(, "hello world"));
cout << mystr << std::endl;

return 0;
}

This correctly prints 'hello world' when compiled with g++. However, this
program fails to compile on VC++. On going through the preprocessor output
in VC++, I found that the macro call line is:
string mystr ();
This expansion is incorrect.
g++ does the correct expansion (as documented:
http://gcc.gnu.org/onlinedocs/gcc-3....p_3.html#SEC15 )
and the output for the same statement for the g++ preprocessor is:
string mystr ("hello world");

On fiddling around a little more, I realised that the VC++ preprocessor
shifts to the left the non-empty arguments passed, if any. For instance, on
changing the macro definition to:
#define B(X, Y) X X
the statement string mystr (B(, "hello world")); got incorrectly
expanded on VC++ to
string mystr ("hello world" "hello world");
while g++ correctly expanded it to
string mystr ( );

I am using VC++ 6.0

-- Saby


Jul 19 '05 #1
Share this Question
Share on Google+
25 Replies


P: n/a
Sabyasachi Basu wrote:
This correctly prints 'hello world' when compiled with g++. However, this
program fails to compile on VC++.


So why don't you compile it with g++ then? You can use that in Windows
also to compile windows binaries. You can get mingw from here:

http://www.mingw.org/

Jul 19 '05 #2

P: n/a
Sabyasachi Basu wrote:
int main()
{
string mystr (B( , "hello world"));

^^^

Passing nothing as an argument results in undefined behavior, so neither
preprocessor is "correct." In C99, this behavior is well-defined and
more-or-less works like you'd assume an empty argument should work, but this is
not yet a part of C++.

Regards,
Paul Mensonides
Jul 19 '05 #3

P: n/a
Paul Mensonides wrote:
Sabyasachi Basu wrote:

int main()
{
string mystr (B( , "hello world"));


^^^

Passing nothing as an argument results in undefined behavior, so neither
preprocessor is "correct." In C99, this behavior is well-defined and
more-or-less works like you'd assume an empty argument should work, but this is
not yet a part of C++.

Regards,
Paul Mensonides


I guess the OP could use:

#define EMPTY

// yada yada yada

string mystr(B(EMPTY, "Hello World"));
Jul 19 '05 #4

P: n/a
red floyd wrote:
I guess the OP could use:

#define EMPTY

// yada yada yada

string mystr(B(EMPTY, "Hello World"));


Yes, so long as it only goes through one level of expansion:

#define EMPTY

#define A(x) x

A(EMPTY) // okay

#define X(p) Y(p)
#define Y(p) p

X(EMPTY) // undefined behavior

Regards,
Paul Mensonides
Jul 19 '05 #5

P: n/a
I don't think this behaviour is undefined, going by the GNU documentation,
at least.

Here is what it has to say:
http://gcc.gnu.org/onlinedocs/gcc-3....p_3.html#SEC16
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code). You cannot
leave out arguments entirely; if a macro takes two arguments, there must be
exactly one comma at the top level of its argument list. "

Regards,
Saby
"Paul Mensonides" <le******@comcast.net> wrote in message
news:7aW4b.246870$cF.79001@rwcrnsc53...
Sabyasachi Basu wrote:
int main()
{
string mystr (B( , "hello world")); ^^^

Passing nothing as an argument results in undefined behavior, so neither
preprocessor is "correct." In C99, this behavior is well-defined and
more-or-less works like you'd assume an empty argument should work, but

this is not yet a part of C++.

Regards,
Paul Mensonides

Jul 19 '05 #6

P: n/a
I am afraid, the path is not open for me. This is a small contrived snippet
of code that I wrote to illustrate the problem. The actual software that I
need to port, runs into hundreds of thousands of lines and it needs to be
compiled with VC++ on Windows.

Regards,
Sabya

"Aggro" <sp**********@yahoo.com> wrote in message
news:T7************@read3.inet.fi...
Sabyasachi Basu wrote:
This correctly prints 'hello world' when compiled with g++. However, this program fails to compile on VC++.


So why don't you compile it with g++ then? You can use that in Windows
also to compile windows binaries. You can get mingw from here:

http://www.mingw.org/

Jul 19 '05 #7

P: n/a
On Tue, 2 Sep 2003 14:05:03 +0530, "Sabyasachi Basu" <sabya_01 AT hot
mail DOTcom> wrote in comp.lang.c:
I don't think this behaviour is undefined, going by the GNU documentation,
at least.

Here is what it has to say:
http://gcc.gnu.org/onlinedocs/gcc-3....p_3.html#SEC16
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code). You cannot
leave out arguments entirely; if a macro takes two arguments, there must be
exactly one comma at the top level of its argument list. "

Regards,
Saby


The GNU compiler does not define the language, the ISO standard does.
Omitting arguments from macros is not now, and never has been, legal
in the C++ language. It is possible to write macros with variable
arguments under the latest C standard, but not in this form.

Visual C++, at least through version 6, does not support this in
either C or C++.

If you want portability, write portable code and do not use
non-standard compiler extensions.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Jul 19 '05 #8

P: n/a
> I don't think this behaviour is undefined, going by the GNU
documentation,
at least.

Here is what it has to say:
http://gcc.gnu.org/onlinedocs/gcc-3....p_3.html#SEC16
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code). You cannot leave out arguments entirely; if a macro takes two arguments, there must be exactly one comma at the top level of its argument list. "


It may be defined behaviour for the G++ compiler, however that doesn't
mean it is defined behaviour according to the C++ standard. The G++
compiler supports several features that are not defined in the C++
standard.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 19 '05 #9

P: n/a
Yes, that would work if there were only level of macro expansion. However,
the following program is closer to what actually exists in my code. The
preprocessor correctly expands EMPTY to blank when expanding the first
level; however, it ends up in the same situation as before when it passes
that blank to the next macro.

#include <iostream>
#include <string>
using namespace std;

#define EMPTY
#define B(X, Y) Y
#define XY(X, Y) \
B(X, Y)

int main()
{
string mystr (XY(EMPTY, "hello world"));
cout << mystr << std::endl;
return 0;
}

Compiling...
testmacro.cpp
C:\Work\testmacro\testmacro.cpp(14) : warning C4003: not enough actual
parameters for macro 'B'
Linking...
testmacro.obj : error LNK2001: unresolved external symbol "class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > __cdecl mystr(void)"
(?mystr@@YA?AV?$basic_string@DU?$char_traits@D@std @@V?$allocator@D@2@@std@@X
Z)
Debug/testmacro.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

testmacro.exe - 2 error(s), 1 warning(s)
"red floyd" <no*****@here.dude> wrote in message
news:9K******************@newssvr25.news.prodigy.c om...
#define EMPTY

// yada yada yada

string mystr(B(EMPTY, "Hello World"));

Jul 19 '05 #10

P: n/a
On Tue, 2 Sep 2003, Jack Klein wrote:
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code). You cannot
leave out arguments entirely; if a macro takes two arguments, there must be
exactly one comma at the top level of its argument list. "


The GNU compiler does not define the language, the ISO standard does.
Omitting arguments from macros is not now, and never has been, legal
in the C++ language. It is possible to write macros with variable
arguments under the latest C standard, but not in this form.


Huh?

"Major changes from the previous edition include:
-- empty macro arguments"

Jul 19 '05 #11

P: n/a
*** rude topposting fixed ***

Sabyasachi Basu wrote:
"Paul Mensonides" <le******@comcast.net> wrote in message
Sabyasachi Basu wrote:
int main()
{
string mystr (B( , "hello world"));

^^^

Passing nothing as an argument results in undefined behavior,
so neither preprocessor is "correct." In C99, this behavior
is well-defined and more-or-less works like you'd assume an
empty argument should work, but this is not yet a part of C++.


I don't think this behaviour is undefined, going by the GNU
documentation, at least.

Here is what it has to say:
http://gcc.gnu.org/onlinedocs/gcc-3....p_3.html#SEC16
"You can leave macro arguments empty; this is not an error to
the preprocessor (but many macros will then expand to invalid
code). You cannot leave out arguments entirely; if a macro
takes two arguments, there must be exactly one comma at the
top level of its argument list. "


Please do not toppost, and please make up your mind if you are
dealing with C++ or with C. The languages are different.

The GNU documentation has nothing to do with what is portable in
either language. The only appropriate documentation is the
relevant ISO standards, which are available. Suitable gcc
switches can restrict gcc to standard portable code, which is the
only subject of this newsgroup (c.l.c).

For C at least, the C99 standard allows for variable argument
lists to macros, but this is not yet widely implemented. The C90
standard does not allow such. For C++ see a C++ newsgroup (I am
reading in c.l.c).

You might be best off rewriting your macros, and thus the macro
calls, for portability. Remember that macros perform text
replacement, and that the components must be suitable language
components. You could put tests in the actual macros to
eliminate specific arguments, using #if statements. Then the
calls might be something like:

B(NULL, "Hello world");

--
Replies should be to the newsgroup
Chuck Falconer, on vacation.
Jul 19 '05 #12

P: n/a
Sabyasachi Basu wrote:
I don't think this behaviour is undefined, going by the GNU
documentation, at least.

Here is what it has to say:
http://gcc.gnu.org/onlinedocs/gcc-3....p_3.html#SEC16
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code). You
cannot leave out arguments entirely; if a macro takes two arguments,
there must be exactly one comma at the top level of its argument
list. "


C++ Standard - 16.3/10 - ."...If (before argument substitution) any argument
consists of no preprocessing tokens, the behavior is undefined...."

The C99 standard, explicitly allows and defines the semantics for empty
arguments--a.k.a. placemarkers.

Regards,
Paul Mensonides
Jul 19 '05 #13

P: n/a
Jarno A Wuolijoki wrote:
On Tue, 2 Sep 2003, Jack Klein wrote:
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code).
You cannot leave out arguments entirely; if a macro takes two
arguments, there must be exactly one comma at the top level of its
argument list. "


The GNU compiler does not define the language, the ISO standard does.
Omitting arguments from macros is not now, and never has been, legal
in the C++ language. It is possible to write macros with variable
arguments under the latest C standard, but not in this form.


Huh?

"Major changes from the previous edition include:
-- empty macro arguments"


C99 allows both placemarkers (empty arguments) and variadic arguments. Either
or both can be empty, but delineating commas are still necessary. E.g.

#define A(a, b) // ...

A() // illegal
A(,) // okay

#define B(...) // ...

B() // okay
B(,) // okay

Regards,
Paul Mensonides
Jul 19 '05 #14

P: n/a
Sabyasachi Basu wrote:
Yes, that would work if there were only level of macro expansion.
However, the following program is closer to what actually exists in
my code. The preprocessor correctly expands EMPTY to blank when
expanding the first level; however, it ends up in the same situation
as before when it passes that blank to the next macro.

#include <iostream>
#include <string>
using namespace std;

#define EMPTY
#define B(X, Y) Y
#define XY(X, Y) \
B(X, Y)

int main()
{
string mystr (XY(EMPTY, "hello world"));
cout << mystr << std::endl;
return 0;
}


Then do something like this:

#include <iostream>
#include <string>
using namespace std;

#define EMPTY()
#define IDENTITY(x) x EMPTY

#define B(x, y) y()
#define XY(x, y) B(x, y)

int main()
{
string mystr (XY(EMPTY, IDENTITY("hello world")));
cout << mystr << std::endl;
return 0;
}

Regards,
Paul Mensonides
Jul 19 '05 #15

P: n/a
"Sabyasachi Basu" <sabya_01 AT hot mail DOTcom> wrote in message news:<3f******@news.cadence.com>...
Yes, that would work if there were only level of macro expansion. However,
the following program is closer to what actually exists in my code. The
preprocessor correctly expands EMPTY to blank when expanding the first
level; however, it ends up in the same situation as before when it passes
that blank to the next macro.

#include <iostream>
#include <string>
using namespace std;

#define EMPTY
#define B(X, Y) Y
#define XY(X, Y) \
B(X, Y)

int main()
{
string mystr (XY(EMPTY, "hello world"));
cout << mystr << std::endl;
return 0;
}


Since B and XY (via B) discard the first parameter, why don't you just use...

#define EMPTY EMPTY

--
Peter
Jul 19 '05 #16

P: n/a
On Tue, 02 Sep 2003 19:18:57 GMT, "Paul Mensonides"
<le******@comcast.net> wrote in comp.lang.c:
Jarno A Wuolijoki wrote:
On Tue, 2 Sep 2003, Jack Klein wrote:
"You can leave macro arguments empty; this is not an error to the
preprocessor (but many macros will then expand to invalid code).
You cannot leave out arguments entirely; if a macro takes two
arguments, there must be exactly one comma at the top level of its
argument list. "

The GNU compiler does not define the language, the ISO standard does.
Omitting arguments from macros is not now, and never has been, legal
in the C++ language. It is possible to write macros with variable
arguments under the latest C standard, but not in this form.


Huh?

"Major changes from the previous edition include:
-- empty macro arguments"


C99 allows both placemarkers (empty arguments) and variadic arguments. Either
or both can be empty, but delineating commas are still necessary. E.g.

#define A(a, b) // ...

A() // illegal
A(,) // okay

#define B(...) // ...

B() // okay
B(,) // okay

Regards,
Paul Mensonides


Oops, my mistake. I was aware of the variadic arguments, unaware of
the placeholders, which would make the OP's code usable, perhaps. Of
course the OP never said what version of VC he needed to use. I know
for a fact that 6.0 doesn't.

Any ideas what VC++ 7.1 claims for C99 conformance?

If he "has" to compile it with VC++, and VC++ doesn't support this,
there's always writing a program to fix the source code, perhaps
change each macro invocation into one of several closely related
macros depending on how many arguments are actually present.

Could do this in C, in Perl, in quite a few text editors, even.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Jul 19 '05 #17

P: n/a
Jack Klein wrote:
Any ideas what VC++ 7.1 claims for C99 conformance?


Nothing.

-cd
Jul 19 '05 #18

P: n/a
On Tue, 2 Sep 2003 20:18:42 -0700, "Carl Daniel [VC++ MVP]"
<cp******@nospam.mvps.org> wrote in comp.lang.c:
Jack Klein wrote:
Any ideas what VC++ 7.1 claims for C99 conformance?


Nothing.

-cd


Not surprised.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Jul 19 '05 #19

P: n/a
> You might be best off rewriting your macros, and thus the macro
calls, for portability. Remember that macros perform text
replacement, and that the components must be suitable language
components. You could put tests in the actual macros to
eliminate specific arguments, using #if statements. Then the
calls might be something like:

B(NULL, "Hello world");


How do I use #if directives to put tests in the actual macros? Arent
preprocessor directives disallowed within macro definitions?

Jul 19 '05 #20

P: n/a
Jack Klein wrote:
On Tue, 2 Sep 2003 20:18:42 -0700, "Carl Daniel [VC++ MVP]"
<cp******@nospam.mvps.org> wrote in comp.lang.c:
Jack Klein wrote:
Any ideas what VC++ 7.1 claims for C99 conformance?


Nothing.

-cd


Not surprised.


According to VC team members I've talkd to, there's close to zero customer
interest in C99 conformance. The commonly mentioned exceptions being
variadic macro arguments and the standardized fixed-sized integer types.

-cd
Jul 19 '05 #21

P: n/a
In article <#4**************@tk2msftngp13.phx.gbl>,
cp******@nospam.mvps.org says...
Any ideas what VC++ 7.1 claims for C99 conformance?

Nothing.


According to VC team members I've talkd to, there's close to zero customer
interest in C99 conformance. The commonly mentioned exceptions being
variadic macro arguments and the standardized fixed-sized integer types.


Interesting. I've been an MSDN subscriber for as long as the program has
been in place and I've never been asked once what I'd like to see in the
next release of any product. How do they know? Do you have to email some
spamtrap address at Microsoft to get this type of thing requested?

--
Randy Howard _o
2reply remove FOOBAR \<,
______________________()/ ()______________________________________________
SCO Spam-magnet: po********@sco.com
Jul 19 '05 #22

P: n/a

"Randy Howard" <ra**********@FOOmegapathdslBAR.net> wrote in message

Interesting. I've been an MSDN subscriber for as long as the program has
been in place and I've never been asked once what I'd like to see in the
next release of any product. How do they know? Do you have to email some
spamtrap address at Microsoft to get this type of thing requested?


I've never got asked either. But I've long contended both in the microsoft.*
forums and to any Microsoft employee who asked that standards compliance
is fairly high up there on my list of concerns.
Jul 19 '05 #23

P: n/a
I wonder what valuable features except variadic macro arguments C99 gives? I
don't quite understand a reason for evolving C.
Want 'complex' type - go for C++, want variable-sized arrays - go for C++,
etc.

"Carl Daniel [VC++ MVP]" <cp******@nospam.mvps.org> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
Jack Klein wrote:
On Tue, 2 Sep 2003 20:18:42 -0700, "Carl Daniel [VC++ MVP]"
<cp******@nospam.mvps.org> wrote in comp.lang.c:
Jack Klein wrote:
Any ideas what VC++ 7.1 claims for C99 conformance?

Nothing.

-cd


Not surprised.


According to VC team members I've talkd to, there's close to zero customer
interest in C99 conformance. The commonly mentioned exceptions being
variadic macro arguments and the standardized fixed-sized integer types.

-cd

Jul 19 '05 #24

P: n/a
Your way is <Ctrl> <H>...

Gnum
Jul 19 '05 #25

P: n/a
Randy Howard wrote:
cp******@nospam.mvps.org says...
>> Any ideas what VC++ 7.1 claims for C99 conformance?
>
> Nothing.


According to VC team members I've talkd to, there's close to
zero customer interest in C99 conformance. The commonly
mentioned exceptions being variadic macro arguments and the
standardized fixed-sized integer types.


Interesting. I've been an MSDN subscriber for as long as the
program has been in place and I've never been asked once what
I'd like to see in the next release of any product. How do they
know? Do you have to email some spamtrap address at Microsoft
to get this type of thing requested?


I suspect that the real meaning of "customer interest" is
"compliance doesn not enhance Microsoft domination" and/or
"compliance would encourage use of non-Microsoft software in the
marketplace".

--
Replies should be to the newsgroup
Chuck Falconer, on vacation.
Jul 19 '05 #26

This discussion thread is closed

Replies have been disabled for this discussion.