Understanding assert code

Discussion in 'C Programming' started by Sami, Nov 5, 2010.

  1. Sami

    Sami Guest

    Hi

    I am using some C code with the following macro:

    #define __force_assert(x) ((assert)(x))

    Can anyone explain what is going on here.

    Thanks.
    Sami, Nov 5, 2010
    #1
    1. Advertising

  2. Sami

    Ben Pfaff Guest

    Sami <> writes:

    > I am using some C code with the following macro:
    >
    > #define __force_assert(x) ((assert)(x))


    This will invoke a function named assert, ignoring any
    function-like macro of the same name.

    That's puzzling. The C standard says that assert is a macro. It
    doesn't say anything about an assert function. I don't know
    anyone would want to do this.
    --
    Ben Pfaff
    http://benpfaff.org
    Ben Pfaff, Nov 5, 2010
    #2
    1. Advertising

  3. Sami

    Seebs Guest

    On 2010-11-05, Sami <> wrote:
    > Hi
    >
    > I am using some C code with the following macro:
    >
    > #define __force_assert(x) ((assert)(x))
    >
    > Can anyone explain what is going on here.


    Someone is trying to be clever.

    assert(x) aborts if x is untrue... Sometimes.

    If you #define the symbol NDEBUG before including <assert.h>,
    assert(x) is a no-op.

    Now, since this is happening in the preprocessor, Our Protagonist
    has concluded that obviously, this is done by re-defining the
    name "assert", which is presumably a function-like macro. (He's
    probably right; in particular, it can't be a non-function-like macro,
    I don't think, because so far as I can tell you're allowed to have
    a variable named that, though it might be unwise.)

    So he's using (assert) to try to force the compiler to generate
    an actual call to the assert() function rather than macroing it
    away. This might work, because function-like-macros are only
    expanded when the next thing after the macro name is a left
    parens. Instead, he's arranged for it to be a right parens.

    I would never do this.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Nov 5, 2010
    #3
  4. Ben Pfaff <> writes:
    > Sami <> writes:
    >> I am using some C code with the following macro:
    >>
    >> #define __force_assert(x) ((assert)(x))

    >
    > This will invoke a function named assert, ignoring any
    > function-like macro of the same name.
    >
    > That's puzzling. The C standard says that assert is a macro. It
    > doesn't say anything about an assert function. I don't know
    > anyone would want to do this.


    I suppose someone (not the C implementation) might provide a function
    called "assert", but that would be a silly thing to do.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 5, 2010
    #4
  5. Kenneth Brody <> writes:
    > On 11/5/2010 2:40 PM, Keith Thompson wrote:
    >> Ben Pfaff<> writes:
    >>> Sami<> writes:
    >>>> I am using some C code with the following macro:
    >>>>
    >>>> #define __force_assert(x) ((assert)(x))
    >>>
    >>> This will invoke a function named assert, ignoring any
    >>> function-like macro of the same name.
    >>>
    >>> That's puzzling. The C standard says that assert is a macro. It
    >>> doesn't say anything about an assert function. I don't know
    >>> anyone would want to do this.

    >>
    >> I suppose someone (not the C implementation) might provide a function
    >> called "assert", but that would be a silly thing to do.

    >
    > Well, the assert() macro becomes a no-op if NDEBUG is #defined. It appears
    > that this implementation has created __force_assert() which remains in
    > effect even in the presence of NDEBUG.


    The OP didn't say that the implementation created it.

    If it is part of the implementation, it might actually be reasonable;
    it could be a way to provide something that acts like the standard
    assert() macro but that isn't affected by NDEBUG.

    If it's not part of the implementation, then the use of a reserved
    name starting with "__" is ill-advised, as is the assumption that
    there's an actual function called "assert".

    Also, an actual function can't produce a message containing the text
    of the argument and the values of __FILE__, __LINE__, and __func__.

    Sami, where did you see this? Is it part of a program, or is it
    in a header provided by the implementation?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 5, 2010
    #5
  6. Sami

    Sami Guest

    Keith Thompson writes:

    > Kenneth Brody <> writes:
    >> On 11/5/2010 2:40 PM, Keith Thompson wrote:
    >>> Ben Pfaff<> writes:
    >>>> Sami<> writes:
    >>>>> I am using some C code with the following macro:
    >>>>>
    >>>>> #define __force_assert(x) ((assert)(x))
    >>>>
    >>>> This will invoke a function named assert, ignoring any function-like
    >>>> macro of the same name.
    >>>>
    >>>> That's puzzling. The C standard says that assert is a macro. It
    >>>> doesn't say anything about an assert function. I don't know anyone
    >>>> would want to do this.
    >>>
    >>> I suppose someone (not the C implementation) might provide a function
    >>> called "assert", but that would be a silly thing to do.

    >>
    >> Well, the assert() macro becomes a no-op if NDEBUG is #defined. It
    >> appears that this implementation has created __force_assert() which
    >> remains in effect even in the presence of NDEBUG.

    >
    > The OP didn't say that the implementation created it.
    >
    > If it is part of the implementation, it might actually be reasonable; it
    > could be a way to provide something that acts like the standard assert()
    > macro but that isn't affected by NDEBUG.
    >
    > If it's not part of the implementation, then the use of a reserved name
    > starting with "__" is ill-advised, as is the assumption that there's an
    > actual function called "assert".
    >
    > Also, an actual function can't produce a message containing the text of
    > the argument and the values of __FILE__, __LINE__, and __func__.
    >
    > Sami, where did you see this? Is it part of a program, or is it in a
    > header provided by the implementation?


    Hi Kieth,

    The codebase I'm working on has a couple of executables and a shared DLL.
    One of the headers in this DLL provides __force_assert.

    An example of how it's used in the code is:

    char * fname_new = strdup(fname);
    __force_assert( fname_new != NULL );

    Most functions and macros in the DLL have a __ prefix, I guess to avoid
    polluting the executable's "namespace".
    Sami, Nov 6, 2010
    #6
  7. Sami <> writes:
    > Keith Thompson writes:

    [...]
    >>>>> Sami<> writes:
    >>>>>> I am using some C code with the following macro:
    >>>>>>
    >>>>>> #define __force_assert(x) ((assert)(x))

    [...]
    >> Sami, where did you see this? Is it part of a program, or is it in a
    >> header provided by the implementation?

    >
    > Hi Kieth,


    It's "Keith".

    > The codebase I'm working on has a couple of executables and a shared DLL.
    > One of the headers in this DLL provides __force_assert.
    >
    > An example of how it's used in the code is:
    >
    > char * fname_new = strdup(fname);
    > __force_assert( fname_new != NULL );


    Where is the "assert" function declared or defined? The standard C
    header <assert.h> defines a *macro* called "assert"; it doesn't declare
    a function by that name. On the implementation I use, there is no
    assert() function; this:
    #include <assert.h>
    ...
    assert(0);
    fails to compile.

    > Most functions and macros in the DLL have a __ prefix, I guess to avoid
    > polluting the executable's "namespace".


    That's a bad idea. Rather than polluting the executable's namespace,
    it's polluting the implementation's namespace.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 6, 2010
    #7
  8. Sami

    Ben Pfaff Guest

    Keith Thompson <> writes:

    > Where is the "assert" function declared or defined? The standard C
    > header <assert.h> defines a *macro* called "assert"; it doesn't declare
    > a function by that name. On the implementation I use, there is no
    > assert() function; this:
    > #include <assert.h>
    > ...
    > assert(0);
    > fails to compile.


    Why? (I'm assuming that you actually put that statement inside a
    function body.)
    --
    Ben Pfaff
    http://benpfaff.org
    Ben Pfaff, Nov 6, 2010
    #8
  9. Ben Pfaff <> writes:
    > Keith Thompson <> writes:
    >> Where is the "assert" function declared or defined? The standard C
    >> header <assert.h> defines a *macro* called "assert"; it doesn't declare
    >> a function by that name. On the implementation I use, there is no
    >> assert() function; this:
    >> #include <assert.h>
    >> ...
    >> assert(0);
    >> fails to compile.

    >
    > Why? (I'm assuming that you actually put that statement inside a
    > function body.)


    Because, rather than following the advice I give several times a
    week to copy-and-paste actual code rather than paraphrasing it by
    re-typing it, I paraphrased the actual code by re-typing it and
    got it wrong in a way that destroyed the point I was trying to make.

    Here's the actual code:

    #include <assert.h>
    int main(void) {
    (assert)(0);
    return 0;
    }

    And here are the error messages from the compiler:

    c.c: In function ‘main’:
    c.c:3: error: ‘assert’ undeclared (first use in this function)
    c.c:3: error: (Each undeclared identifier is reported only once
    c.c:3: error: for each function it appears in.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 6, 2010
    #9
  10. Sami

    Eric Sosman Guest

    On 11/6/2010 5:06 PM, Keith Thompson wrote:
    > Ben Pfaff<> writes:
    >> Keith Thompson<> writes:
    >>> Where is the "assert" function declared or defined? The standard C
    >>> header<assert.h> defines a *macro* called "assert"; it doesn't declare
    >>> a function by that name. On the implementation I use, there is no
    >>> assert() function; this:
    >>> #include<assert.h>
    >>> ...
    >>> assert(0);
    >>> fails to compile.

    >>
    >> Why? (I'm assuming that you actually put that statement inside a
    >> function body.)

    >
    > Because, rather than following the advice I give several times a
    > week to copy-and-paste actual code rather than paraphrasing it by
    > re-typing it, I paraphrased the actual code by re-typing it and
    > got it wrong in a way that destroyed the point I was trying to make.
    >
    > Here's the actual code:
    >
    > #include<assert.h>
    > int main(void) {
    > (assert)(0);
    > return 0;
    > }
    >
    > And here are the error messages from the compiler:
    >
    > c.c: In function ‘main’:
    > c.c:3: error: ‘assert’ undeclared (first use in this function)
    > c.c:3: error: (Each undeclared identifier is reported only once
    > c.c:3: error: for each function it appears in.)


    Interestingly, the diagnostic is not required. Quoth the
    Standard: "If the macro definition is suppressed in order to access
    an actual function, the behavior is undefined," and "undefined"
    includes the possibility that no diagnostic appears, that the code
    compiles, and that any oddities happen at run-time.

    It seems to me that the authors of the macro (reproduced here
    for reference):

    #define __force_assert(x) ((assert)(x))

    .... were trying to be responsible citizens, but didn't quite think
    things through. If an implementation's assert() macro actually
    generates a call on an assert() helper function (which it may), this
    __force_assert() macro necessarily generates an incorrect call. (Of
    course, the assert() implementation might be magical -- but in that
    case, the __force_assert() kludge is on even thinner ice!)

    --
    Eric Sosman
    lid
    Eric Sosman, Nov 6, 2010
    #10
  11. Sami

    Sami Guest

    Keith Thompson writes:
    > Sami <> writes:
    >> Keith Thompson writes:

    > [...]
    >>>>>> Sami<> writes:
    >>>>>>> I am using some C code with the following macro:
    >>>>>>>
    >>>>>>> #define __force_assert(x) ((assert)(x))

    > [...]
    >>> Sami, where did you see this? Is it part of a program, or is it in a
    >>> header provided by the implementation?

    >>
    >> Hi Kieth,

    >
    > It's "Keith".
    >
    >> The codebase I'm working on has a couple of executables and a shared
    >> DLL. One of the headers in this DLL provides __force_assert.
    >>
    >> An example of how it's used in the code is:
    >>
    >> char * fname_new = strdup(fname);
    >> __force_assert( fname_new != NULL );

    >
    > Where is the "assert" function declared or defined? The standard C
    > header <assert.h> defines a *macro* called "assert"; it doesn't declare
    > a function by that name. On the implementation I use, there is no
    > assert() function; this:
    > #include <assert.h>
    > ...
    > assert(0);
    > fails to compile.
    >
    >> Most functions and macros in the DLL have a __ prefix, I guess to avoid
    >> polluting the executable's "namespace".

    >
    > That's a bad idea. Rather than polluting the executable's namespace,
    > it's polluting the implementation's namespace.


    Hi

    Could you explain what you mean by "the implementation" in this context?

    You may be aware that C only has one global namespace - the only
    exception is variables with static storage which have symbols only tied
    to a single object file.
    Sami, Nov 7, 2010
    #11
  12. Sami

    Seebs Guest

    On 2010-11-07, Sami <> wrote:
    > Keith Thompson writes:
    >> That's a bad idea. Rather than polluting the executable's namespace,
    >> it's polluting the implementation's namespace.


    > Could you explain what you mean by "the implementation" in this context?


    The implementation is the C compiler and its support code -- the
    name seems self-explanatory. It is the implementation of C you're
    using.

    > You may be aware that C only has one global namespace - the only
    > exception is variables with static storage which have symbols only tied
    > to a single object file.


    Yes. However, some names are reserved for the implementation to use.
    It is always undefined behavior for a program to use those names, even
    if the implementation happens not to be using them yet. This is because
    implementations often need additional helper functions or macros or
    whatnot, and we don't want those names to break user programs.

    So those names are reserved for the implementation, and when the "clever"
    programmer uses __force_assert, he's stepping into a general category
    of names (two leading underscores) which is reserved for someone else.

    In short, yes, C has only one "global namespace" -- but it is useful
    to distinguish between "the set of all names reserved for the
    implementation and prohibited to developers" and "the set of all names
    reserved for software developers and prohibited to the implementation".
    We tend to refer to the latter as "the implementation's namespace".

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Nov 7, 2010
    #12
  13. Seebs wrote:
    > In short, yes, C has only one "global namespace" -- but it is useful
    > to distinguish between "the set of all names reserved for the
    > implementation and prohibited to developers" and "the set of all names
    > reserved for software developers and prohibited to the implementation".
    > We tend to refer to the latter as "the implementation's namespace".


    The former, not the latter.
    --
    Marcin Grzegorczyk
    Marcin Grzegorczyk, Nov 7, 2010
    #13
  14. Sami

    Seebs Guest

    On 2010-11-07, Marcin Grzegorczyk <> wrote:
    > Seebs wrote:
    >> In short, yes, C has only one "global namespace" -- but it is useful
    >> to distinguish between "the set of all names reserved for the
    >> implementation and prohibited to developers" and "the set of all names
    >> reserved for software developers and prohibited to the implementation".
    >> We tend to refer to the latter as "the implementation's namespace".


    > The former, not the latter.


    This kind of attention to detail is why I *love* code review.

    I am very good at getting the hard parts right, but the easy parts
    mystify me.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Nov 7, 2010
    #14
  15. Sami

    Tim Rentsch Guest

    Eric Sosman <> writes:

    > On 11/6/2010 5:06 PM, Keith Thompson wrote:
    >> Ben Pfaff<> writes:
    >>> Keith Thompson<> writes:
    >>>> Where is the "assert" function declared or defined? The standard C
    >>>> header<assert.h> defines a *macro* called "assert"; it doesn't declare
    >>>> a function by that name. On the implementation I use, there is no
    >>>> assert() function; this:
    >>>> #include<assert.h>
    >>>> ...
    >>>> assert(0);
    >>>> fails to compile.
    >>>
    >>> Why? (I'm assuming that you actually put that statement inside a
    >>> function body.)

    >>
    >> Because, rather than following the advice I give several times a
    >> week to copy-and-paste actual code rather than paraphrasing it by
    >> re-typing it, I paraphrased the actual code by re-typing it and
    >> got it wrong in a way that destroyed the point I was trying to make.
    >>
    >> Here's the actual code:
    >>
    >> #include<assert.h>
    >> int main(void) {
    >> (assert)(0);
    >> return 0;
    >> }
    >>
    >> And here are the error messages from the compiler:
    >>
    >> c.c: In function 'main':
    >> c.c:3: error: 'assert' undeclared (first use in this function)
    >> c.c:3: error: (Each undeclared identifier is reported only once
    >> c.c:3: error: for each function it appears in.)

    >
    > Interestingly, the diagnostic is not required. Quoth the
    > Standard: "If the macro definition is suppressed in order to access
    > an actual function, the behavior is undefined," and "undefined"
    > includes the possibility that no diagnostic appears, that the code
    > compiles, and that any oddities happen at run-time. [snip]


    I'm not sure if you're meaning to make a subtle point or if
    you've just overlooked something. If the identifier 'assert' is
    not declared (or defined as an enumeration constant), then in
    fact a diagnostic must be issued. The Standard is quite clear
    about this, in 5.1.1.3p1, when it says a diagnostic must be
    produced whenever there is

    a violation of any syntax rule or constraint, even if
    the behavior is also explicitly specified as undefined
    or implementation-defined.

    If 'assert' hasn't been declared (or defined as an enumeration
    constant), then it doesn't match the syntax for primary-expression,
    which requires a diagnostic, even if there is undefined behavior.

    The subtlety is whether <assert.h> is allowed to declare 'assert'
    as a regular identifier (or define it as an enumeration constant).
    My impression is that it is not. For example, consider

    enum blah { assert = 0 };
    #include <assert.h>
    int main(){ return assert; }

    I believe this program is supposed to be strictly conforming.

    Another possibility: could 'assert' be defined as an object-like
    macro rather than a function-like macro? Again my impression is
    that it cannot. Another program:

    struct { int assert; } x = 0;
    #include <assert.h>
    int main(){ return x.assert; }

    Here again I believe this program is supposed to be strictly
    conforming. More specifically, for both programs I'm not
    aware of any restriction that has been violated.

    The weak point of the above comments is that the Standard never
    says specifically (at least not as far as I'm aware) that the
    definition for 'assert' must be as a function-like macro and not as
    an object-like macro (assuming NDEBUG is not defined). However,
    all the evidence I'm aware of makes the 'must be a function-like
    macro' choice appear to be the more reasonable one.
    Tim Rentsch, Nov 9, 2010
    #15
    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. Robert Brewer
    Replies:
    1
    Views:
    486
    bsmith
    Nov 7, 2004
  2. Thomas Guettler

    assert 0, "foo" vs. assert(0, "foo")

    Thomas Guettler, Feb 23, 2005, in forum: Python
    Replies:
    3
    Views:
    2,519
    Carl Banks
    Feb 23, 2005
  3. Alex Vinokur

    assert(x) and '#define ASSERT(x) assert(x)'

    Alex Vinokur, Nov 25, 2004, in forum: C Programming
    Replies:
    5
    Views:
    911
    Keith Thompson
    Nov 25, 2004
  4. Replies:
    29
    Views:
    744
    mlimber
    Oct 17, 2006
  5. ImpalerCore

    To assert or not to assert...

    ImpalerCore, Apr 27, 2010, in forum: C Programming
    Replies:
    79
    Views:
    1,658
    Richard Bos
    May 17, 2010
Loading...

Share This Page