Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #161988 > unrolled thread
| Started by | John Forkosh <forkosh@panix.com> |
|---|---|
| First post | 2021-07-20 11:15 +0000 |
| Last post | 2021-07-20 08:47 -0700 |
| Articles | 20 on this page of 51 — 11 participants |
Back to article view | Back to comp.lang.c
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 →
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-07-20 11:15 +0000 |
| Subject | How 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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-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]
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-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]
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-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]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-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]
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-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]
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-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