function argument evaluation order and asserts and macros

Discussion in 'C++' started by jacek.dziedzic@gmail.com, Sep 24, 2008.

  1. Guest

    Hi!

    I am for defensive programming and am working on a code stuffed with
    quite a lot of assert-like statements, like

    Asserts(pos==pos,"Position #"+to_string(i)+" is NaN");

    where Asserts is

    #define Asserts(expr,s) \
    if(!(expr))
    Framework::Asserts_Fail(__STRING(expr),__FILE__,__LINE__,__PRETTY_FUNCTION__,s)

    and Asserts_Fail() displays a bunch of info and terminates the
    program.

    My question: a typical assert falls through 99.999% of the time as
    if(!(expr)) is false. Am I guaranteed though, that the std::string
    "Position #number is NaN" would not be constructed in vain _every
    time_ this assert is checked? My understanding is that since this is a
    macro, not a function call, then it is only constructed when the
    assert actually clicks and Asserts_Fail() is called. If Asserts() was
    made to be a function call instead of a macro, then I might not be as
    lucky.

    Can anyone confirm or contradict this?

    TIA,
    - J.
    , Sep 24, 2008
    #1
    1. Advertising

  2. writes:

    > Hi!
    >
    > I am for defensive programming and am working on a code stuffed with
    > quite a lot of assert-like statements, like
    >
    > Asserts(pos==pos,"Position #"+to_string(i)+" is NaN");
    >
    > where Asserts is
    >
    > #define Asserts(expr,s) \
    > if(!(expr))
    > Framework::Asserts_Fail(__STRING(expr),__FILE__,__LINE__,__PRETTY_FUNCTION__,s)
    >
    > and Asserts_Fail() displays a bunch of info and terminates the
    > program.
    >
    > My question: a typical assert falls through 99.999% of the time as
    > if(!(expr)) is false. Am I guaranteed though, that the std::string
    > "Position #number is NaN" would not be constructed in vain _every
    > time_ this assert is checked? My understanding is that since this is a
    > macro, not a function call, then it is only constructed when the
    > assert actually clicks and Asserts_Fail() is called. If Asserts() was
    > made to be a function call instead of a macro, then I might not be as
    > lucky.
    >
    > Can anyone confirm or contradict this?


    Yes, emacs can.


    Put your source in some buffer named test.c:
    ------------------------------------------------------------------------
    #define Asserts(expr,s) \
    if(!(expr)) Framework::Asserts_Fail(__STRING(expr),__FILE__,__LINE__,__PRETTY_FUNCTION__,s)


    Asserts(pos==pos,"Position #"+to_string(i)+" is NaN");
    ------------------------------------------------------------------------

    Select it and type C-x C-e ; it will open another buffer containing
    the code with the macros expanded:
    ------------------------------------------------------------------------




    if(!(pos==pos)) Framework::Asserts_Fail(__STRING(pos==pos),"a.c",5,__PRETTY_FUNCTION__,"Position #"+to_string(i)+" is NaN");
    ------------------------------------------------------------------------

    If you don't have emacs, you can run the c preprocessor on the source:

    gcc -E -o test.e test.c && cat test.e


    So you can see that indeed, the expansion of the macro is purely
    textual, and the the concatenation will occur only when the assertion
    is false.

    --
    __Pascal Bourguignon__
    Pascal J. Bourguignon, Sep 24, 2008
    #2
    1. Advertising

  3. James Kanze Guest

    On Sep 24, 9:45 am, wrote:

    > I am for defensive programming and am working on a code
    > stuffed with quite a lot of assert-like statements, like


    > Asserts(pos==pos,"Position #"+to_string(i)+" is NaN");


    > where Asserts is


    > #define Asserts(expr,s) \
    > if(!(expr))
    > Framework::Asserts_Fail(__STRING(expr),__FILE__,__LINE__,__PRETTY_FUNCTION__,s)


    > and Asserts_Fail() displays a bunch of info and terminates the
    > program.


    That's a very unusual definition. I've generally seen something
    more like:

    ((expr) || Framework::Asserts_Fail( ... ))

    The idea being that the expansion of the macro is a pure
    expression, and can be used anywhere an expression can be used
    (and if there is support for turning it off, the macro expands
    to something like "((void)0)").

    > My question: a typical assert falls through 99.999% of the time as
    > if(!(expr)) is false.


    More often than that, one would hope. In production code, it
    should fall through 100% of the time.

    > Am I guaranteed though, that the std::string "Position #number
    > is NaN" would not be constructed in vain _every time_ this
    > assert is checked?


    Obviously. With both versions above. Including if the macro
    was passed a string expression.

    > My understanding is that since this is a macro, not a function
    > call, then it is only constructed when the assert actually
    > clicks and Asserts_Fail() is called. If Asserts() was made to
    > be a function call instead of a macro, then I might not be as
    > lucky.


    > Can anyone confirm or contradict this?


    Macros are, well, macros. They are expanded textually by the
    compiler. What happens after that depends on the results of the
    textual expansion.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Sep 24, 2008
    #3
  4. Guest

    On Sep 24, 10:42 am, (Pascal J. Bourguignon)
    wrote:
    > So you can see that indeed, the expansion of the macro is purely
    > textual, and the the concatenation will occur only when the assertion
    > is false.


    Thank you.
    , Sep 24, 2008
    #4
  5. Guest

    On Sep 24, 11:06 am, James Kanze <> wrote:
    > That's a very unusual definition.  I've generally seen something
    > more like:


    Yes, I rolled my own without seeing how it's typically done.

    >
    >     ((expr) || Framework::Asserts_Fail( ... ))
    >
    > The idea being that the expansion of the macro is a pure
    > expression, and can be used anywhere an expression can be used
    > (and if there is support for turning it off, the macro expands
    > to something like "((void)0)").


    Yes, I can see the advantage.

    > > My question: a typical assert falls through 99.999% of the time as
    > > if(!(expr)) is false.

    >
    > More often than that, one would hope.  In production code, it
    > should fall through 100% of the time.


    I'm very far from production code :).

    > Macros are, well, macros.  They are expanded textually by the
    > compiler.  What happens after that depends on the results of the
    > textual expansion.


    Right, thanks for the confirmation.
    , Sep 24, 2008
    #5
    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. Ken
    Replies:
    5
    Views:
    1,427
    Guus Bosman
    May 22, 2004
  2. KKramsch

    newbie Q: C's asserts in C++

    KKramsch, Dec 3, 2004, in forum: C++
    Replies:
    10
    Views:
    628
    Alex Vinokur
    Dec 7, 2004
  3. Timothy Grant

    py.test munging strings in asserts?

    Timothy Grant, Apr 21, 2006, in forum: Python
    Replies:
    1
    Views:
    302
    Johnny deBris
    Apr 21, 2006
  4. martinus

    redesigning JUnit asserts

    martinus, Aug 4, 2006, in forum: Java
    Replies:
    0
    Views:
    393
    martinus
    Aug 4, 2006
  5. Anthony de Almeida Lopes

    Macros within function-like macros?

    Anthony de Almeida Lopes, Dec 26, 2005, in forum: C Programming
    Replies:
    13
    Views:
    748
Loading...

Share This Page