Re: rvalue

From: Chris Torek (nospam_at_torek.net)
Date: 04/10/04


Date: 10 Apr 2004 00:23:00 GMT

In article <news:lnwu4oq1u0.fsf@nuthaus.mib.org>
Keith Thompson <kst-u@mib.org> writs:
>The outer parentheses surrounding the entire macro definition are
>necessary (and the original version of the macro had them). I was
>referring to parentheses around each parameter reference within the
>macro definition:
>
>#define POSITION(mw,row) (+(mw).positions[(row)])
>
>I'm fairly sure that the parentheses around row are unnecessary, since
>it's already immediately surrounded by square brackets. I'm less
>certain about the parentheses surrounding mw; I can't think of any
>possible problems, but I could be missing something.

There is one case where they are required.

For any such macro to work, the macro parameter "mw" must name a
structure object that has a "positions" field. This field is either
an array of size N, or a pointer that points to the first of N
sequential elements.

Suppose we redefine the macro as just:

    #define POSITION(mw, row) (+mw.positions[row])

Typically this might be used as:

    struct S var;

    ... POSITION(var, k) ...

which works as desired. The macro expands to:

    (+var.positions[k])

which parses as "access the k'th element of the array or pointer
named via the positions member of the variable `var', then apply
the unary + operator". But suppose instead we have a pointer,
e.g.:

    struct S *ptr = ...;

    ... POSITION(*ptr, k) ...

In this case, the version without parentheses expands to:

    (+*ptr.positions[k])

which parses the same as:

    (+(*(ptr.positions[k])))

This attempts to apply the unary "*" and binary "." operators
to the wrong operands.

Parenthesizing "mw" in the expansion gives, instead:

    (+(*ptr).positions[k])

which now applies unary "*" to "ptr" as desired, and binary "."
to the structure found via *ptr.

The parentheses around "row" are in fact unnecessary. (A good
proof requires exhaustive enumeration, but a hand-wavey version
simply notes that the square brackets function identically to
parentheses, provided the expression in "row" is syntactically
legal to begin with. Writing POSITION(*ptr,]) causes problems,
but these problems are not fixable via parentheses.)

-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W)  +1 801 277 2603
email: forget about it   http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.


Relevant Pages

  • Re: C the complete nonsense
    ... he correctly parenthesizes the formal parameters in the macro, ... Very few C programmers in practice take the next step, ... curly brackets and expression macros in round parentheses. ...
    (comp.lang.c)
  • Re: C99: Suggestions for style(9)
    ... because it does not improve maintainability in any way. ... There is no source for confusion here, so the rule even contradicts the rule, which states not to use redundant parentheses. ... so it is clear that there is a macro at work. ... the parentheses are not redundant) would be for local debugging ...
    (freebsd-hackers)
  • Re: Compare to a defined constants in C?
    ... int main ... doesn't need a semicolon to terminate it; ... Another thing to watch out for is that a macro that's to be used ... Judicious use of parentheses can avoid most problems. ...
    (comp.lang.c)
  • Re: Casting the return value of malloc()...
    ... If the operand is a macro, and the macro is defined in such a way that ... parentheses are necessary, *fix the macro definition*. ... enclose the operand in parentheses or omit the parentheses. ... Idiom is more robust. ...
    (comp.lang.c)