473,398 Members | 2,088 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

C preprocessor function macros with empty aguments

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
25 9056
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
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
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
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
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
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
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
> 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
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
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
*** 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
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
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
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
"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
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
Jack Klein wrote:
Any ideas what VC++ 7.1 claims for C99 conformance?


Nothing.

-cd
Jul 19 '05 #18
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
> 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
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
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

"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
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
Your way is <Ctrl> <H>...

Gnum
Jul 19 '05 #25
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

205
by: Jeremy Siek | last post by:
CALL FOR PAPERS/PARTICIPATION C++, Boost, and the Future of C++ Libraries Workshop at OOPSLA October 24-28, 2004 Vancouver, British Columbia, Canada http://tinyurl.com/4n5pf Submissions
27
by: Sabyasachi Basu | last post by:
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...
7
by: Newbie_sw2003 | last post by:
Where should I use them? I am giving you my understandings. Please correct me if I am wrong: MACRO: e.g.:#define ref-name 99 The code is substituted by the MACRO ref-name. So no overhead....
4
by: Jim Ford | last post by:
I have a single C file with the following code: int f2() { /* Blah-blah */ } int f1() { /* Blah-blah */
6
by: max(01)* | last post by:
hi. i want to examine preprocessed source which only has certain macros expanded, for example i would like to have: #include <stdio.h> #include "other.c" int main() { ... }
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.