C preprocessor function macros with empty aguments

Discussion in 'C Programming' started by Sabyasachi Basu, Sep 2, 2003.

  1. 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.0.1/cpp_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
     
    Sabyasachi Basu, Sep 2, 2003
    #1
    1. Advertising

  2. Sabyasachi Basu

    Aggro Guest

    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/
     
    Aggro, Sep 2, 2003
    #2
    1. Advertising

  3. 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
     
    Paul Mensonides, Sep 2, 2003
    #3
  4. Sabyasachi Basu

    red floyd Guest

    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"));
     
    red floyd, Sep 2, 2003
    #4
  5. 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
     
    Paul Mensonides, Sep 2, 2003
    #5
  6. 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.0.1/cpp_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" <> 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
    >
    >
     
    Sabyasachi Basu, Sep 2, 2003
    #6
  7. 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" <> wrote in message
    news:T7W4b.38$...
    > 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/
    >
     
    Sabyasachi Basu, Sep 2, 2003
    #7
  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.0.1/cpp_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
     
    Peter van Merkerk, Sep 2, 2003
    #8
  9. Sabyasachi Basu

    Jack Klein Guest

    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.0.1/cpp_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
     
    Jack Klein, Sep 2, 2003
    #9
  10. 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" <> wrote in message
    news:9KW4b.10210$...

    > #define EMPTY
    >
    > // yada yada yada
    >
    > string mystr(B(EMPTY, "Hello World"));
    >
    >
     
    Sabyasachi Basu, Sep 2, 2003
    #10
  11. 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"
     
    Jarno A Wuolijoki, Sep 2, 2003
    #11
  12. Sabyasachi Basu

    LibraryUser Guest

    *** rude topposting fixed ***

    Sabyasachi Basu wrote:
    > "Paul Mensonides" <> 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.0.1/cpp_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.
     
    LibraryUser, Sep 2, 2003
    #12
  13. LibraryUser <> wrote in
    <>:
    >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).


    Right. And the whole thread has been cross-posted to:

    comp.lang.c, comp.lang.c++, microsoft.public.vc.language

    < This reply is posted to c.l.c only :p >

    --
    If you don't care where you are, then you ain't lost.
     
    Irrwahn Grausewitz, Sep 2, 2003
    #13
  14. 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.0.1/cpp_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
     
    Paul Mensonides, Sep 2, 2003
    #14
  15. 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
     
    Paul Mensonides, Sep 2, 2003
    #15
  16. 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
     
    Paul Mensonides, Sep 2, 2003
    #16
  17. "Sabyasachi Basu" <sabya_01 AT hot mail DOTcom> wrote in message news:<>...
    > 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
     
    Peter Nilsson, Sep 3, 2003
    #17
  18. Sabyasachi Basu

    Jack Klein Guest

    On Tue, 02 Sep 2003 19:18:57 GMT, "Paul Mensonides"
    <> 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
     
    Jack Klein, Sep 3, 2003
    #18
  19. Jack Klein wrote:
    > Any ideas what VC++ 7.1 claims for C99 conformance?


    Nothing.

    -cd
     
    Carl Daniel [VC++ MVP], Sep 3, 2003
    #19
  20. Sabyasachi Basu

    Jack Klein Guest

    Jack Klein, Sep 3, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sabyasachi Basu
    Replies:
    25
    Views:
    810
    LibraryUser
    Sep 5, 2003
  2. Cronus
    Replies:
    1
    Views:
    677
    Paul Mensonides
    Jul 15, 2004
  3. Jay Wolfe

    preprocessor macros

    Jay Wolfe, Feb 17, 2005, in forum: C++
    Replies:
    4
    Views:
    482
    Walter
    Feb 18, 2005
  4. Anthony de Almeida Lopes

    Macros within function-like macros?

    Anthony de Almeida Lopes, Dec 26, 2005, in forum: C Programming
    Replies:
    13
    Views:
    768
  5. Telmo Costa

    function and arguments as aguments

    Telmo Costa, Feb 15, 2006, in forum: Javascript
    Replies:
    40
    Views:
    472
    Richard Cornford
    Feb 20, 2006
Loading...

Share This Page