Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #161988 > unrolled thread

How to disambiguate macro?

Started byJohn Forkosh <forkosh@panix.com>
First post2021-07-20 11:15 +0000
Last post2021-07-20 08:47 -0700
Articles 20 on this page of 51 — 11 participants

Back to article view | Back to comp.lang.c


Contents

  How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-20 11:15 +0000
    Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-20 13:49 +0100
      Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-20 12:56 +0000
        Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-20 15:36 +0100
          Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-21 01:48 +0000
            Re: How to disambiguate macro? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-20 19:18 -0700
            Re: How to disambiguate macro? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-20 20:27 -0700
              Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-21 04:15 +0000
                Re: How to disambiguate macro? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-21 02:00 -0700
                Re: How to disambiguate macro? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-21 06:02 -0400
            Re: How to disambiguate macro? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-21 06:00 -0400
              Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-21 10:10 +0000
                Re: How to disambiguate macro? Bart <bc@freeuk.com> - 2021-07-21 11:30 +0100
                Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-21 13:31 +0200
                Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-21 13:02 +0100
                  Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-21 14:20 +0100
                    Re: How to disambiguate macro? Bart <bc@freeuk.com> - 2021-07-21 15:15 +0100
                      Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-21 16:28 +0200
                      Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-21 16:20 +0100
                        Re: How to disambiguate macro? Bart <bc@freeuk.com> - 2021-07-21 17:34 +0100
                          Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-21 19:46 +0200
                            Re: How to disambiguate macro? Manfred <noname@add.invalid> - 2021-07-21 20:42 +0200
                              Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-22 08:37 +0200
                            Re: How to disambiguate macro? Bart <bc@freeuk.com> - 2021-07-21 20:47 +0100
                              Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-22 08:47 +0200
                                Re: How to disambiguate macro? Bart <bc@freeuk.com> - 2021-07-22 11:31 +0100
                                Re: How to disambiguate macro? antispam@math.uni.wroc.pl - 2021-07-22 14:37 +0000
                                  Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-22 18:15 +0200
                          Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-21 21:19 +0100
                  Re: How to disambiguate macro? Manfred <noname@add.invalid> - 2021-07-21 15:42 +0200
                    Re: How to disambiguate macro? scott@slp53.sl.home (Scott Lurndal) - 2021-07-21 15:39 +0000
                Re: How to disambiguate macro? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-21 09:22 -0700
                Re: How to disambiguate macro? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-21 17:24 -0400
                  Re: How to disambiguate macro? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-21 16:42 -0700
                    Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-22 05:49 +0000
                      Re: How to disambiguate macro? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-22 19:11 -0400
                  Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-22 05:30 +0000
                    Re: How to disambiguate macro? scott@slp53.sl.home (Scott Lurndal) - 2021-07-22 14:14 +0000
                    Re: How to disambiguate macro? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-22 17:06 +0100
                  OT: possessive adjectives (Was: How to disambiguate macro?) Manfred <noname@add.invalid> - 2021-07-22 15:04 +0200
                    Re: OT: possessive adjectives Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-08-14 13:37 -0700
            Re: How to disambiguate macro? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-08-14 13:58 -0700
    Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-20 14:50 +0200
      Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-20 13:19 +0000
        Re: How to disambiguate macro? Bart <bc@freeuk.com> - 2021-07-20 14:40 +0100
          Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-20 21:02 +0200
        Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-20 21:00 +0200
        Re: How to disambiguate macro? David Brown <david.brown@hesbynett.no> - 2021-07-21 08:15 +0200
        Re: How to disambiguate macro? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-08-14 23:17 -0700
    Re: How to disambiguate macro? John Forkosh <forkosh@panix.com> - 2021-07-20 12:51 +0000
    Re: How to disambiguate macro? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-20 08:47 -0700

Page 1 of 3  [1] 2 3  Next page →


#161988 — How to disambiguate macro?

FromJohn Forkosh <forkosh@panix.com>
Date2021-07-20 11:15 +0000
SubjectHow to disambiguate macro?
Message-ID<sd6b8j$498$1@reader1.panix.com>
Consider a macro of the form
/* --- set north=parent,south=child,east=next,west=previous link of node --- */
   #define setlink(ptr,nsew,link) if ( checknode(ptr) ) \
                           ((node *)(ptr))->nsew  = (node *)(link)
Not important exactly what it does, just the  if(xxx)yyy  construction.

Now, suppose I want to use it like
   if ( xxx ) setlink(a,b,c); else yyy;
Then the compiler warns that the binding of that  else yyy;  is ambiguous.

I clearly mean
   if ( xxx ) {setlink(a,b,c);} else yyy;
but it's cumbersome and inelegant to write it that way again and again.

Likewise, if I try to define the macro with the {}'s (and the trailing ;)
   #define setlink(ptr,nsew,link) { if ( checknode(ptr) ) \
                           ((node *)(ptr))->nsew  = (node *)(link); }
Then writing  setlink(a,b,c);  in the code has that extraneous ; which
can then again cause the same kind of confusion. But omitting the ; just
looks wrong and ugly.

So what's a way to define the macro that simultaneously removes
any potential semantic confusion without introducing the necessity of
any unpretty syntax?
-- 
John Forkosh  ( mailto:  j@f.com  where j=john and f=forkosh )

[toc] | [next] | [standalone]


#161989

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-07-20 13:49 +0100
Message-ID<878s21gney.fsf@bsb.me.uk>
In reply to#161988
John Forkosh <forkosh@panix.com> writes:

> Consider a macro of the form
> /* --- set north=parent,south=child,east=next,west=previous link of node --- */
>    #define setlink(ptr,nsew,link) if ( checknode(ptr) ) \
>                            ((node *)(ptr))->nsew  = (node *)(link)
> Not important exactly what it does, just the  if(xxx)yyy  construction.
>
> Now, suppose I want to use it like
>    if ( xxx ) setlink(a,b,c); else yyy;
> Then the compiler warns that the binding of that  else yyy;  is ambiguous.
>
> I clearly mean
>    if ( xxx ) {setlink(a,b,c);} else yyy;
> but it's cumbersome and inelegant to write it that way again and again.
>
> Likewise, if I try to define the macro with the {}'s (and the trailing ;)
>    #define setlink(ptr,nsew,link) { if ( checknode(ptr) ) \
>                            ((node *)(ptr))->nsew  = (node *)(link); }
> Then writing  setlink(a,b,c);  in the code has that extraneous ; which
> can then again cause the same kind of confusion. But omitting the ; just
> looks wrong and ugly.
>
> So what's a way to define the macro that simultaneously removes
> any potential semantic confusion without introducing the necessity of
> any unpretty syntax?

There is a conventional idiom for this:

#define setlink(ptr,nsew,link)                    \
  do {                                            \
     if ( checknode(ptr) )                        \
         ((node *)(ptr))->nsew  = (node *)(link); \
  } while (0)

(The {}s are optional in this case.)

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#161992

FromJohn Forkosh <forkosh@panix.com>
Date2021-07-20 12:56 +0000
Message-ID<sd6h5j$hng$2@reader1.panix.com>
In reply to#161989
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> John Forkosh <forkosh@panix.com> writes:
> 
>> Consider a macro of the form
>> /* --- set north=parent,south=child,east=next,west=previous link of node --- */
>>    #define setlink(ptr,nsew,link) if ( checknode(ptr) ) \
>>                            ((node *)(ptr))->nsew  = (node *)(link)
>> Not important exactly what it does, just the  if(xxx)yyy  construction.
>>
>> Now, suppose I want to use it like
>>    if ( xxx ) setlink(a,b,c); else yyy;
>> Then the compiler warns that the binding of that  else yyy;  is ambiguous.
>>
>> I clearly mean
>>    if ( xxx ) {setlink(a,b,c);} else yyy;
>> but it's cumbersome and inelegant to write it that way again and again.
>>
>> Likewise, if I try to define the macro with the {}'s (and the trailing ;)
>>    #define setlink(ptr,nsew,link) { if ( checknode(ptr) ) \
>>                            ((node *)(ptr))->nsew  = (node *)(link); }
>> Then writing  setlink(a,b,c);  in the code has that extraneous ; which
>> can then again cause the same kind of confusion. But omitting the ; just
>> looks wrong and ugly.
>>
>> So what's a way to define the macro that simultaneously removes
>> any potential semantic confusion without introducing the necessity of
>> any unpretty syntax?
> 
> There is a conventional idiom for this:
> 
> #define setlink(ptr,nsew,link)                    \
>   do {                                            \
>      if ( checknode(ptr) )                        \
>          ((node *)(ptr))->nsew  = (node *)(link); \
>   } while (0)
> 
> (The {}s are optional in this case.)

Thanks. Okay, I'll try adopting that conventional style.
Looks a bit elaborate to me, but if that's the convention
then I guess I can get comfortable with it.
P.S. Oops, you can ignore my followup to myself -- I wrote that
before your (and David's) replies were posted on my newsreader.
-- 
John Forkosh  ( mailto:  j@f.com  where j=john and f=forkosh )

[toc] | [prev] | [next] | [standalone]


#161995

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-07-20 15:36 +0100
Message-ID<87fsw9m4qd.fsf@bsb.me.uk>
In reply to#161992
John Forkosh <forkosh@panix.com> writes:

> Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>> John Forkosh <forkosh@panix.com> writes:
>> 
>>> Consider a macro of the form
>>> /* --- set north=parent,south=child,east=next,west=previous link of node --- */
>>>    #define setlink(ptr,nsew,link) if ( checknode(ptr) ) \
>>>                            ((node *)(ptr))->nsew  = (node *)(link)
>>> Not important exactly what it does, just the  if(xxx)yyy  construction.
>>>
>>> Now, suppose I want to use it like
>>>    if ( xxx ) setlink(a,b,c); else yyy;
>>> Then the compiler warns that the binding of that  else yyy;  is ambiguous.
>>>
>>> I clearly mean
>>>    if ( xxx ) {setlink(a,b,c);} else yyy;
>>> but it's cumbersome and inelegant to write it that way again and again.
>>>
>>> Likewise, if I try to define the macro with the {}'s (and the trailing ;)
>>>    #define setlink(ptr,nsew,link) { if ( checknode(ptr) ) \
>>>                            ((node *)(ptr))->nsew  = (node *)(link); }
>>> Then writing  setlink(a,b,c);  in the code has that extraneous ; which
>>> can then again cause the same kind of confusion. But omitting the ; just
>>> looks wrong and ugly.
>>>
>>> So what's a way to define the macro that simultaneously removes
>>> any potential semantic confusion without introducing the necessity of
>>> any unpretty syntax?
>> 
>> There is a conventional idiom for this:
>> 
>> #define setlink(ptr,nsew,link)                    \
>>   do {                                            \
>>      if ( checknode(ptr) )                        \
>>          ((node *)(ptr))->nsew  = (node *)(link); \
>>   } while (0)
>> 
>> (The {}s are optional in this case.)
>
> Thanks. Okay, I'll try adopting that conventional style.
> Looks a bit elaborate to me, but if that's the convention
> then I guess I can get comfortable with it.

Most C programmers won't bat an eyelid at it, but I agree it's clumsy.

When the contingent action is actually just an expression, you can avoid
the if (...) altogether like this:

#define setlink(ptr,nsew,link) \
   ( checknode(ptr) && (((node *)(ptr))->nsew = (node *)(link)) )

so that there are 'else' issues at all.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#162005

FromJohn Forkosh <forkosh@panix.com>
Date2021-07-21 01:48 +0000
Message-ID<sd7ud2$hkh$1@reader1.panix.com>
In reply to#161995
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> John Forkosh <forkosh@panix.com> writes:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>>> John Forkosh <forkosh@panix.com> writes:
>>> 
>>>> Consider a macro of the form
>>>> /* --- set north=parent,south=child,east=next,west=previous link of node --- */
>>>>    #define setlink(ptr,nsew,link) if ( checknode(ptr) ) \
>>>>                            ((node *)(ptr))->nsew  = (node *)(link)
>>>> Not important exactly what it does, just the  if(xxx)yyy  construction.
>>>>
>>>> Now, suppose I want to use it like
>>>>    if ( xxx ) setlink(a,b,c); else yyy;
>>>> Then the compiler warns that the binding of that  else yyy;  is ambiguous.
>>>>
>>>> I clearly mean
>>>>    if ( xxx ) {setlink(a,b,c);} else yyy;
>>>> but it's cumbersome and inelegant to write it that way again and again.
>>>>
>>>> Likewise, if I try to define the macro with the {}'s (and the trailing ;)
>>>>    #define setlink(ptr,nsew,link) { if ( checknode(ptr) ) \
>>>>                            ((node *)(ptr))->nsew  = (node *)(link); }
>>>> Then writing  setlink(a,b,c);  in the code has that extraneous ; which
>>>> can then again cause the same kind of confusion. But omitting the ; just
>>>> looks wrong and ugly.
>>>>
>>>> So what's a way to define the macro that simultaneously removes
>>>> any potential semantic confusion without introducing the necessity of
>>>> any unpretty syntax?
>>> 
>>> There is a conventional idiom for this:
>>> 
>>> #define setlink(ptr,nsew,link)                    \
>>>   do {                                            \
>>>      if ( checknode(ptr) )                        \
>>>          ((node *)(ptr))->nsew  = (node *)(link); \
>>>   } while (0)
>>> 
>>> (The {}s are optional in this case.)
>>
>> Thanks. Okay, I'll try adopting that conventional style.
>> Looks a bit elaborate to me, but if that's the convention
>> then I guess I can get comfortable with it.
> 
> Most C programmers won't bat an eyelid at it, but I agree it's clumsy.
> 
> When the contingent action is actually just an expression, you can avoid
> the if (...) altogether like this:
> 
> #define setlink(ptr,nsew,link) \
>    ( checknode(ptr) && (((node *)(ptr))->nsew = (node *)(link)) )
> 
> so that there are no 'else' issues at all.

Thanks, again, for the alternative solution. I actually like it
a little better since it avoids the klutzy do-while construction
that has no useful purpose and might only confuse the casual reader,
i.e., "What the heck is he doing that for?" But then again, I never
much liked relying that  (a&&b)  always evaluates a first, immediately
becoming 0 without evaluating b at all if a is itself 0. You never know
exactly what the next C standard might mess around with.
But your suggestion itself suggested the more explicit version
  #define setlink(ptr,nsew,link) \
     ( checknode(ptr)? (((node *)(ptr))->nsew = (node *)(link)) : 0 )
which I think accomplishes the same thing with explicitly visible logic.
-- 
John Forkosh  ( mailto:  j@f.com  where j=john and f=forkosh )

[toc] | [prev] | [next] | [standalone]


#162006

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-07-20 19:18 -0700
Message-ID<sd805a$qr8$1@dont-email.me>
In reply to#162005
On 7/20/2021 6:48 PM, John Forkosh wrote:
> 
> Thanks, again, for the alternative solution. I actually like it
> a little better since it avoids the klutzy do-while construction
> that has no useful purpose and might only confuse the casual reader,
> i.e., "What the heck is he doing that for?" 
> 

Such "casual reader" has no business looking into such implementation 
details. The 'do/while(0)' idiom is so classic, well-established and 
universally known that anyone qualified enough to be curious about the 
innards of your macro will immediately recognize it and understand its 
purpose. As for the others... it might actually be a good thing if it 
scares them away.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#162007

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-07-20 20:27 -0700
Message-ID<87eebs1h4j.fsf@nosuchdomain.example.com>
In reply to#162005
John Forkosh <forkosh@panix.com> writes:
> Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
[...]
>> When the contingent action is actually just an expression, you can avoid
>> the if (...) altogether like this:
>> 
>> #define setlink(ptr,nsew,link) \
>>    ( checknode(ptr) && (((node *)(ptr))->nsew = (node *)(link)) )
>> 
>> so that there are no 'else' issues at all.
>
> Thanks, again, for the alternative solution. I actually like it
> a little better since it avoids the klutzy do-while construction
> that has no useful purpose and might only confuse the casual reader,
> i.e., "What the heck is he doing that for?" But then again, I never
> much liked relying that  (a&&b)  always evaluates a first, immediately
> becoming 0 without evaluating b at all if a is itself 0. You never know
> exactly what the next C standard might mess around with.
> But your suggestion itself suggested the more explicit version
>   #define setlink(ptr,nsew,link) \
>      ( checknode(ptr)? (((node *)(ptr))->nsew = (node *)(link)) : 0 )
> which I think accomplishes the same thing with explicitly visible logic.

The "do .. while (0)" idiom is very widely know.  All C programmers
*should* know about it.  If the macro body is intended to be used in at
statement context, that idiom is, as far as I know, the only method that
actually works in all cases.  Saying that it "has no useful purpose" is
incorrect.

It's question 10.4 in the comp.lang.c FAQ, http://www.c-faq.com/

If you can make the macro expansion an expression instead, that's good,
but you can't do so in all cases.  An if/then can often be rewritten
using the &&, ||, or ?: operator.  A loop cannot.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162008

FromJohn Forkosh <forkosh@panix.com>
Date2021-07-21 04:15 +0000
Message-ID<sd871m$r0p$1@reader1.panix.com>
In reply to#162007
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
> John Forkosh <forkosh@panix.com> writes:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> [...]
>>> When the contingent action is actually just an expression, you can avoid
>>> the if (...) altogether like this:
>>> 
>>> #define setlink(ptr,nsew,link) \
>>>    ( checknode(ptr) && (((node *)(ptr))->nsew = (node *)(link)) )
>>> 
>>> so that there are no 'else' issues at all.
>>
>> Thanks, again, for the alternative solution. I actually like it
>> a little better since it avoids the klutzy do-while construction
>> that has no useful purpose and might only confuse the casual reader,
>> i.e., "What the heck is he doing that for?" But then again, I never
>> much liked relying that  (a&&b)  always evaluates a first, immediately
>> becoming 0 without evaluating b at all if a is itself 0. You never know
>> exactly what the next C standard might mess around with.
>> But your suggestion itself suggested the more explicit version
>>   #define setlink(ptr,nsew,link) \
>>      ( checknode(ptr)? (((node *)(ptr))->nsew = (node *)(link)) : 0 )
>> which I think accomplishes the same thing with explicitly visible logic.
> 
> The "do .. while (0)" idiom is very widely know.  All C programmers
> *should* know about it.  If the macro body is intended to be used in at
> statement context, that idiom is, as far as I know, the only method that
> actually works in all cases.  Saying that it "has no useful purpose" is
> incorrect.

I just meant that the semantics of do{xxx;}while(0); is identical
to just xxx; without the decoration.

> It's question 10.4 in the comp.lang.c FAQ, http://www.c-faq.com/
> 
> If you can make the macro expansion an expression instead, that's good,
> but you can't do so in all cases.  An if/then can often be rewritten
> using the &&, ||, or ?: operator.  A loop cannot.
> 

-- 
John Forkosh  ( mailto:  j@f.com  where j=john and f=forkosh )

[toc] | [prev] | [next] | [standalone]


#162010

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-07-21 02:00 -0700
Message-ID<87a6mg11p9.fsf@nosuchdomain.example.com>
In reply to#162008
John Forkosh <forkosh@panix.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>> John Forkosh <forkosh@panix.com> writes:
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>> [...]
>>>> When the contingent action is actually just an expression, you can avoid
>>>> the if (...) altogether like this:
>>>> 
>>>> #define setlink(ptr,nsew,link) \
>>>>    ( checknode(ptr) && (((node *)(ptr))->nsew = (node *)(link)) )
>>>> 
>>>> so that there are no 'else' issues at all.
>>>
>>> Thanks, again, for the alternative solution. I actually like it
>>> a little better since it avoids the klutzy do-while construction
>>> that has no useful purpose and might only confuse the casual reader,
>>> i.e., "What the heck is he doing that for?" But then again, I never
>>> much liked relying that  (a&&b)  always evaluates a first, immediately
>>> becoming 0 without evaluating b at all if a is itself 0. You never know
>>> exactly what the next C standard might mess around with.
>>> But your suggestion itself suggested the more explicit version
>>>   #define setlink(ptr,nsew,link) \
>>>      ( checknode(ptr)? (((node *)(ptr))->nsew = (node *)(link)) : 0 )
>>> which I think accomplishes the same thing with explicitly visible logic.
>> 
>> The "do .. while (0)" idiom is very widely know.  All C programmers
>> *should* know about it.  If the macro body is intended to be used in at
>> statement context, that idiom is, as far as I know, the only method that
>> actually works in all cases.  Saying that it "has no useful purpose" is
>> incorrect.
>
> I just meant that the semantics of do{xxx;}while(0); is identical
> to just xxx; without the decoration.

By itself, yes, but not in the context of a macro definition (which
omits the trailing semicolon, BTW).

>> It's question 10.4 in the comp.lang.c FAQ, http://www.c-faq.com/
>> 
>> If you can make the macro expansion an expression instead, that's good,
>> but you can't do so in all cases.  An if/then can often be rewritten
>> using the &&, ||, or ?: operator.  A loop cannot.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162012

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-07-21 06:02 -0400
Message-ID<sd8rbp$fph$2@dont-email.me>
In reply to#162008
On 7/21/21 12:15 AM, John Forkosh wrote:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>> John Forkosh <forkosh@panix.com> writes:
...
>>> Thanks, again, for the alternative solution. I actually like it
>>> a little better since it avoids the klutzy do-while construction
>>> that has no useful purpose and might only confuse the casual reader,
>>> i.e., "What the heck is he doing that for?" ...
...
>> The "do .. while (0)" idiom is very widely know.  All C programmers
>> *should* know about it.  If the macro body is intended to be used in at
>> statement context, that idiom is, as far as I know, the only method that
>> actually works in all cases.  Saying that it "has no useful purpose" is
>> incorrect.
> 
> I just meant that the semantics of do{xxx;}while(0); is identical
> to just xxx; without the decoration.

It's not a question of "do{xxx;} while(0);" vs. "xxx;". It's a key point
of the idiom that it's "do{xxx; yyy;} while(0)"  vs. "{xxx; yyy;}". A
function-like macro should not include the terminating ";", because it
would result in a syntax error if used in various locations where a
function would be perfectly legal. And the problem that "do {xxx; yyy;}
while()" is designed to avoid isn't a problem unless there's at least
two statements inside the {}.

See the following for a more detailed explanation:

>> It's question 10.4 in the comp.lang.c FAQ, http://www.c-faq.com/

[toc] | [prev] | [next] | [standalone]


#162011

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-07-21 06:00 -0400
Message-ID<sd8r8p$fph$1@dont-email.me>
In reply to#162005
On 7/20/21 9:48 PM, John Forkosh wrote:
...
> i.e., "What the heck is he doing that for?" But then again, I never
> much liked relying that  (a&&b)  always evaluates a first, immediately
> becoming 0 without evaluating b at all if a is itself 0. You never know
> exactly what the next C standard might mess around with.

That is a pretty fundamental feature of C; it's one of the last features
of C that I would ever expect to see changed. It would break far too
much existing code.

[toc] | [prev] | [next] | [standalone]


#162013

FromJohn Forkosh <forkosh@panix.com>
Date2021-07-21 10:10 +0000
Message-ID<sd8rra$f4o$1@reader1.panix.com>
In reply to#162011
James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
> On 7/20/21 9:48 PM, John Forkosh wrote:
> ...
>> i.e., "What the heck is he doing that for?" But then again, I never
>> much liked relying that  (a&&b)  always evaluates a first, immediately
>> becoming 0 without evaluating b at all if a is itself 0. You never know
>> exactly what the next C standard might mess around with.
> 
> That is a pretty fundamental feature of C; it's one of the last features
> of C that I would ever expect to see changed. It would break far too
> much existing code.

I wouldn't be too complacent about that in the future.
And even today I wouldn't be so blithely sure.
For example, && is commutative, i.e., a&&b == b&&a.
So suppose you're compiling with -O3 optimization,
and your program contains something like...
   ( (very_very_complicated_expression) && (++n>3) )
So maybe the optimizer says to itself, "Hey, I'll
just execute that very simple right-hand-side first,
and if it's false then I don't have to bother evaluating
that very complicated left-hand-side at all. Could save lots
of time." Now maybe that's not supposed to happen,
but it's way too subtle for my liking.

I'd never consider a&&b to mean that a is a guard on b's execution.
It certainly doesn't look like a guard, and I wouldn't
trust interpreting it that way. Clearly very bad practice
and very bad advice, even if it happens to work.
-- 
John Forkosh  ( mailto:  j@f.com  where j=john and f=forkosh )

[toc] | [prev] | [next] | [standalone]


#162014

FromBart <bc@freeuk.com>
Date2021-07-21 11:30 +0100
Message-ID<sd8t0p$qqp$1@dont-email.me>
In reply to#162013
On 21/07/2021 11:10, John Forkosh wrote:
> James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>> On 7/20/21 9:48 PM, John Forkosh wrote:
>> ...
>>> i.e., "What the heck is he doing that for?" But then again, I never
>>> much liked relying that  (a&&b)  always evaluates a first, immediately
>>> becoming 0 without evaluating b at all if a is itself 0. You never know
>>> exactly what the next C standard might mess around with.
>>
>> That is a pretty fundamental feature of C; it's one of the last features
>> of C that I would ever expect to see changed. It would break far too
>> much existing code.
> 
> I wouldn't be too complacent about that in the future.
> And even today I wouldn't be so blithely sure.
> For example, && is commutative, i.e., a&&b == b&&a.
> So suppose you're compiling with -O3 optimization,
> and your program contains something like...
>     ( (very_very_complicated_expression) && (++n>3) )
> So maybe the optimizer says to itself, "Hey, I'll
> just execute that very simple right-hand-side first,
> and if it's false then I don't have to bother evaluating
> that very complicated left-hand-side at all. Could save lots
> of time." Now maybe that's not supposed to happen,
> but it's way too subtle for my liking.
> 
> I'd never consider a&&b to mean that a is a guard on b's execution.
> It certainly doesn't look like a guard, and I wouldn't
> trust interpreting it that way. Clearly very bad practice
> and very bad advice, even if it happens to work.
> 

Try using (!!a) & (!!b). Or just a & b if you know that both a and b 
will be 0 or 1.

[toc] | [prev] | [next] | [standalone]


#162015

FromDavid Brown <david.brown@hesbynett.no>
Date2021-07-21 13:31 +0200
Message-ID<sd90ij$lan$1@dont-email.me>
In reply to#162013
On 21/07/2021 12:10, John Forkosh wrote:
> James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>> On 7/20/21 9:48 PM, John Forkosh wrote:
>> ...
>>> i.e., "What the heck is he doing that for?" But then again, I never
>>> much liked relying that  (a&&b)  always evaluates a first, immediately
>>> becoming 0 without evaluating b at all if a is itself 0. You never know
>>> exactly what the next C standard might mess around with.
>>
>> That is a pretty fundamental feature of C; it's one of the last features
>> of C that I would ever expect to see changed. It would break far too
>> much existing code.
> 
> I wouldn't be too complacent about that in the future.
> And even today I wouldn't be so blithely sure.

People who know C /can/ be sure about this.

The only situation you need to worry about && not working as
"short-circuit" is if you are dealing with badly broken, buggy, or
partial C compilers.  These do exist, but if you have to use one you
need to know the details and there are going to be large numbers of
issues to consider, not just how && works.

(Different languages can have different rules for &&, just as they can
for any operator.  One gotcha is that in C++, && works as in C for
standard types or anything that converts to a bool, but loses its
special properties if you use an operator overload &&.  Standard
practice is that you should be extraordinarily reluctant to overload the
&& or || operators.)


> For example, && is commutative, i.e., a&&b == b&&a.

No, not in C.

"x = a && b" means:

	if (a) {
		if (b) {
			x = 1;
		} else {
			x = 0;
		}
	} else {
		x = 0;
	}

Compilers are always free to implement these in any way they like, as
long as the results are the same.  If the evaluation of "b" has no side
effects, the compiler can swap the order if that gives better code.  And
it can use bitwise instructions and, multiplication instructions,
conditional jumps or anything else for the implementation as long as it
keeps the correct behaviour and semantics.

> So suppose you're compiling with -O3 optimization,
> and your program contains something like...
>    ( (very_very_complicated_expression) && (++n>3) )
> So maybe the optimizer says to itself, "Hey, I'll
> just execute that very simple right-hand-side first,
> and if it's false then I don't have to bother evaluating
> that very complicated left-hand-side at all. Could save lots
> of time." Now maybe that's not supposed to happen,
> but it's way too subtle for my liking.
> 

The compiler can't do that.

Or, to be more accurate, it /can/ do that - but not if the program would
notice.  So it cannot skip the complicated expression if there are (or
could be) side-effects.  It could do the easy part first if subsequent
code could not be affected by whether "n" is incremented or not.


> I'd never consider a&&b to mean that a is a guard on b's execution.
> It certainly doesn't look like a guard, and I wouldn't
> trust interpreting it that way. Clearly very bad practice
> and very bad advice, even if it happens to work.
> 

Using && for guards is idiomatic C - it is common practice.  It is
particularly common with pointers.

If you prefer to write your guards with "if", that's fine - write
whatever is clearest.  But you need to understand idiomatic coding.

I find it strange that you could be so concerned about the short-circuit
behaviour of &&, and yet be quite happy to rely on exactly the same
feature of ? :

[toc] | [prev] | [next] | [standalone]


#162016

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-07-21 13:02 +0100
Message-ID<87k0ljlvsu.fsf@bsb.me.uk>
In reply to#162013
John Forkosh <forkosh@panix.com> writes:

> James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
>> On 7/20/21 9:48 PM, John Forkosh wrote:
>> ...
>>> i.e., "What the heck is he doing that for?" But then again, I never
>>> much liked relying that  (a&&b)  always evaluates a first, immediately
>>> becoming 0 without evaluating b at all if a is itself 0. You never know
>>> exactly what the next C standard might mess around with.
>> 
>> That is a pretty fundamental feature of C; it's one of the last features
>> of C that I would ever expect to see changed. It would break far too
>> much existing code.
>
> I wouldn't be too complacent about that in the future.

There absolutely zero chance that the semantics of && will change like
that.  It is as deliberate a design choice as any in the language.
Neither B nor BCPL had short-circuit logical operators, relying instead
on bitwise & and |, as did early C.  && and || were deliberately added
to simplify many common operations:

  while (np != 0 && np->data != 0) ...

> And even today I wouldn't be so blithely sure.

I am not "blithely sure", I'm sure for very good reasons!

> For example, && is commutative, i.e., a&&b == b&&a.

&& is not commutative.

<cut>
> I'd never consider a&&b to mean that a is a guard on b's execution.

That is your choice, of course, but that's a big part of what the
operator is for.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#162017

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-07-21 14:20 +0100
Message-ID<8735s7ls5z.fsf@bsb.me.uk>
In reply to#162016
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> Neither B nor BCPL had short-circuit logical operators, relying instead
> on bitwise & and |, as did early C.

Minor correction.  B didn't have short-circuit & and | as such, but it
had a weird rule that in conditional contexts like

  if (a & b) ...

the operator short-circuited!  C rightly ditched this contextual
interpretation in favour of explicitly short-circuiting operators.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#162019

FromBart <bc@freeuk.com>
Date2021-07-21 15:15 +0100
Message-ID<sd9a5q$qs0$1@dont-email.me>
In reply to#162017
On 21/07/2021 14:20, Ben Bacarisse wrote:
> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> 
>> Neither B nor BCPL had short-circuit logical operators, relying instead
>> on bitwise & and |, as did early C.
> 
> Minor correction.  B didn't have short-circuit & and | as such, but it
> had a weird rule that in conditional contexts like
> 
>    if (a & b) ...
> 
> the operator short-circuited!  C rightly ditched this contextual
> interpretation in favour of explicitly short-circuiting operators.
> 

That's not so weird. I used to have something similar (not in C) where 
'A and B' (ie. logical and, also 'or') short-circuited in conditional 
expressions as used in 'if' and 'while' control expressions, which 
tended to be implemented with branching.

But in ordinary expressions, they didn't.

I now have and/or operators that always short-circuit, but I did briefly 
have versions that never short-circuited. I called these 'andb' and 
'orb' (the 'b' meaning evaluate both). However I couldn't think of 
enough use-cases for them.

Evaluation of the second term can usually be forced when needed.

[toc] | [prev] | [next] | [standalone]


#162020

FromDavid Brown <david.brown@hesbynett.no>
Date2021-07-21 16:28 +0200
Message-ID<sd9au6$m5$1@dont-email.me>
In reply to#162019
On 21/07/2021 16:15, Bart wrote:
> On 21/07/2021 14:20, Ben Bacarisse wrote:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> Neither B nor BCPL had short-circuit logical operators, relying instead
>>> on bitwise & and |, as did early C.
>>
>> Minor correction.  B didn't have short-circuit & and | as such, but it
>> had a weird rule that in conditional contexts like
>>
>>    if (a & b) ...
>>
>> the operator short-circuited!  C rightly ditched this contextual
>> interpretation in favour of explicitly short-circuiting operators.
>>
> 
> That's not so weird. I used to have something similar (not in C) where
> 'A and B' (ie. logical and, also 'or') short-circuited in conditional
> expressions as used in 'if' and 'while' control expressions, which
> tended to be implemented with branching.
> 
> But in ordinary expressions, they didn't.

It is perhaps not /weird/, but it is highly confusing and risky in the
face of side-effects.  It is a seriously bad idea.

Borland Pascal (and Delphi) let you choose to make "and" (and "or")
short-circuiting as an optimisation option, controllable locally with
the Pascal equivalent of pragmas.  Again, it is a dangerous idea.

If a language allows side-effects in expressions and sub-expressions,
then the programmer needs to know /exactly/ when they will be executed.
 It's fine to say "a && b" is /always/ short-circuiting, and fine to say
it is /never/ short-circuiting - you know either way.  It is a terrible
idea to say it is /sometimes/ short-circuiting, depending on how the
expression is used.

Of course, if "b" has no side-effects then it might be good for the
compiler to short-circuit it regardless of the language rules - but
that's just optimisation and efficiency, not a matter of language
semantics and program correctness.

> 
> I now have and/or operators that always short-circuit, but I did briefly
> have versions that never short-circuited. I called these 'andb' and
> 'orb' (the 'b' meaning evaluate both). However I couldn't think of
> enough use-cases for them.
> 
> Evaluation of the second term can usually be forced when needed.

[toc] | [prev] | [next] | [standalone]


#162021

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-07-21 16:20 +0100
Message-ID<87sg07k82m.fsf@bsb.me.uk>
In reply to#162019
Bart <bc@freeuk.com> writes:

> On 21/07/2021 14:20, Ben Bacarisse wrote:
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>> 
>>> Neither B nor BCPL had short-circuit logical operators, relying instead
>>> on bitwise & and |, as did early C.
>> Minor correction.  B didn't have short-circuit & and | as such, but it
>> had a weird rule that in conditional contexts like
>>    if (a & b) ...
>> the operator short-circuited!  C rightly ditched this contextual
>> interpretation in favour of explicitly short-circuiting operators.
>
> That's not so weird. I used to have something similar (not in C) where
> 'A and B' (ie. logical and, also 'or') short-circuited in conditional
> expressions as used in 'if' and 'while' control expressions, which
> tended to be implemented with branching.
>
> But in ordinary expressions, they didn't.

I'm don't see how this would persuade someone that it's not weird.  A
private language is never going to be used by someone other than the
world authority on its semantics.

In public-facing languages, such context-sensitive semantics seem to me
to be the epitome of "weird".

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#162024

FromBart <bc@freeuk.com>
Date2021-07-21 17:34 +0100
Message-ID<sd9ib5$qh1$1@dont-email.me>
In reply to#162021
On 21/07/2021 16:20, Ben Bacarisse wrote:
> Bart <bc@freeuk.com> writes:
> 
>> On 21/07/2021 14:20, Ben Bacarisse wrote:
>>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>>
>>>> Neither B nor BCPL had short-circuit logical operators, relying instead
>>>> on bitwise & and |, as did early C.
>>> Minor correction.  B didn't have short-circuit & and | as such, but it
>>> had a weird rule that in conditional contexts like
>>>     if (a & b) ...
>>> the operator short-circuited!  C rightly ditched this contextual
>>> interpretation in favour of explicitly short-circuiting operators.
>>
>> That's not so weird. I used to have something similar (not in C) where
>> 'A and B' (ie. logical and, also 'or') short-circuited in conditional
>> expressions as used in 'if' and 'while' control expressions, which
>> tended to be implemented with branching.
>>
>> But in ordinary expressions, they didn't.
> 
> I'm don't see how this would persuade someone that it's not weird.  A
> private language is never going to be used by someone other than the
> world authority on its semantics.
> 
> In public-facing languages, such context-sensitive semantics seem to me
> to be the epitome of "weird".
> 

In BASIC, "=" was used for assignments, and "=" was also used as an 
equality operator.

Those two contexts didn't clash, so there wasn't any confusion.

It's similar with the special expression that follows if, while etc; the 
language can simply say that is a separate context.

In my case, because control expression were expected to be full of 
branching anyway, but expressions had linear execution. Nowadays 
branchless code is fashionable.

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web