Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

Often statistics are used as a drunken man uses lampposts -- for support rather than illumination.


devel / comp.lang.c / Re: How to disambiguate macro?

SubjectAuthor
* How to disambiguate macro?John Forkosh
+* Re: How to disambiguate macro?Ben Bacarisse
|`* Re: How to disambiguate macro?John Forkosh
| `* Re: How to disambiguate macro?Ben Bacarisse
|  `* Re: How to disambiguate macro?John Forkosh
|   +- Re: How to disambiguate macro?Andrey Tarasevich
|   +* Re: How to disambiguate macro?Keith Thompson
|   |`* Re: How to disambiguate macro?John Forkosh
|   | +- Re: How to disambiguate macro?Keith Thompson
|   | `- Re: How to disambiguate macro?James Kuyper
|   +* Re: How to disambiguate macro?James Kuyper
|   |`* Re: How to disambiguate macro?John Forkosh
|   | +- Re: How to disambiguate macro?Bart
|   | +- Re: How to disambiguate macro?David Brown
|   | +* Re: How to disambiguate macro?Ben Bacarisse
|   | |+* Re: How to disambiguate macro?Ben Bacarisse
|   | ||`* Re: How to disambiguate macro?Bart
|   | || +- Re: How to disambiguate macro?David Brown
|   | || `* Re: How to disambiguate macro?Ben Bacarisse
|   | ||  `* Re: How to disambiguate macro?Bart
|   | ||   +* Re: How to disambiguate macro?David Brown
|   | ||   |+* Re: How to disambiguate macro?Manfred
|   | ||   ||`- Re: How to disambiguate macro?David Brown
|   | ||   |`* Re: How to disambiguate macro?Bart
|   | ||   | `* Re: How to disambiguate macro?David Brown
|   | ||   |  +- Re: How to disambiguate macro?Bart
|   | ||   |  `* Re: How to disambiguate macro?antispam
|   | ||   |   `- Re: How to disambiguate macro?David Brown
|   | ||   `- Re: How to disambiguate macro?Ben Bacarisse
|   | |`* Re: How to disambiguate macro?Manfred
|   | | `- Re: How to disambiguate macro?Scott Lurndal
|   | +- Re: How to disambiguate macro?Andrey Tarasevich
|   | `* Re: How to disambiguate macro?James Kuyper
|   |  +- Re: How to disambiguate macro?Stefan Ram
|   |  +* Re: How to disambiguate macro?Keith Thompson
|   |  |`* Re: How to disambiguate macro?John Forkosh
|   |  | `- Re: How to disambiguate macro?James Kuyper
|   |  +* Re: How to disambiguate macro?John Forkosh
|   |  |+- Re: How to disambiguate macro?Scott Lurndal
|   |  |`- Re: How to disambiguate macro?Ben Bacarisse
|   |  `* OT: possessive adjectives (Was: How to disambiguate macro?)Manfred
|   |   `- Re: OT: possessive adjectivesTim Rentsch
|   `- Re: How to disambiguate macro?Tim Rentsch
+* Re: How to disambiguate macro?David Brown
|`* Re: How to disambiguate macro?John Forkosh
| +* Re: How to disambiguate macro?Bart
| |`- Re: How to disambiguate macro?David Brown
| +- Re: How to disambiguate macro?David Brown
| +- Re: How to disambiguate macro?David Brown
| `- Re: How to disambiguate macro?Tim Rentsch
+- Re: How to disambiguate macro?John Forkosh
`- Re: How to disambiguate macro?Andrey Tarasevich

Pages:123
How to disambiguate macro?

<sd6b8j$498$1@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17572&group=comp.lang.c#17572

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: How to disambiguate macro?
Date: Tue, 20 Jul 2021 11:15:31 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd6b8j$498$1@reader1.panix.com>
Injection-Date: Tue, 20 Jul 2021 11:15:31 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="4392"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Tue, 20 Jul 2021 11:15 UTC

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 )

Re: How to disambiguate macro?

<878s21gney.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17573&group=comp.lang.c#17573

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 13:49:57 +0100
Organization: A noiseless patient Spider
Lines: 39
Message-ID: <878s21gney.fsf@bsb.me.uk>
References: <sd6b8j$498$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="ff971a2e694b10a43f33d9b018b8731a";
logging-data="26328"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+TUAERVlHvWzms8F7V6w9YXqPdw8MwARI="
Cancel-Lock: sha1:PbiznOg8nhzzItPXXwEsUGSJvZA=
sha1:DCfy9ZMZUZCuMxClFqMr89Mcvzk=
X-BSB-Auth: 1.bb171fb58fa5a5b661c7.20210720134957BST.878s21gney.fsf@bsb.me.uk
 by: Ben Bacarisse - Tue, 20 Jul 2021 12:49 UTC

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.

Re: How to disambiguate macro?

<sd6gqq$sjl$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17574&group=comp.lang.c#17574

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 14:50:33 +0200
Organization: A noiseless patient Spider
Lines: 54
Message-ID: <sd6gqq$sjl$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 20 Jul 2021 12:50:34 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="c69f62bd9394cf34fa01f675d7718bd4";
logging-data="29301"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18uCV4lgSEZcmsegmESa333bGTgZ02R7mg="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:/YIasejUy6NLT1UmdU2a2ySurTc=
In-Reply-To: <sd6b8j$498$1@reader1.panix.com>
Content-Language: en-GB
 by: David Brown - Tue, 20 Jul 2021 12:50 UTC

On 20/07/2021 13:15, John Forkosh wrote:
> 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?
>

The best solution, when you can, is to use inline (or static inline)
functions instead of macros. They are clearer, nicer to write, and
safer to use.

But if you can't avoid using a macro, wrap the contents in a "do { ... }
while (0)" loop. This will be executed exactly once, but avoids
complicated interactions with calling code with conditionals.

And I recommend you get in the habit of writing :

if (xxx) {
setlink(a, b, c);
} else {
yyy;
}

People vary in their opinions and styles, of course, and there may be
overriding concerns (such as matching existing code). But the use of
brackets and indentation here means there can never be any doubts or
ambiguities, with the structure immediately obvious to any reader and no
concerns about whether the apparent code structure matches the actual
structure seen by the compiler. It is a style used by people who value
code safety and correctness higher than code compactness. (K&R call it
"the one true brace style".)

Re: How to disambiguate macro?

<sd6grr$hng$1@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17575&group=comp.lang.c#17575

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 12:51:07 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd6grr$hng$1@reader1.panix.com>
References: <sd6b8j$498$1@reader1.panix.com>
Injection-Date: Tue, 20 Jul 2021 12:51:07 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="18160"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Tue, 20 Jul 2021 12:51 UTC

John Forkosh <forkosh@panix.com> wrote:
> 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?

Hmm... I'm thinking that maybe
/* --- 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); else
might work. That is, throw in an empty else-clause at the end of the macro
so that the caller's trailing ; when writing setlink(a,b,c); just
gets expanded as ...else ; which should permit the compiler to
unambiguously bind the else's. Will that work without warnings?
And is there any other situation where it might cause a problem?
--
John Forkosh ( mailto: j@f.com where j=john and f=forkosh )

Re: How to disambiguate macro?

<sd6h5j$hng$2@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17576&group=comp.lang.c#17576

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 12:56:19 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd6h5j$hng$2@reader1.panix.com>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
Injection-Date: Tue, 20 Jul 2021 12:56:19 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="18160"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Tue, 20 Jul 2021 12:56 UTC

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 )

Re: How to disambiguate macro?

<sd6igi$jos$1@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17577&group=comp.lang.c#17577

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 13:19:14 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd6igi$jos$1@reader1.panix.com>
References: <sd6b8j$498$1@reader1.panix.com> <sd6gqq$sjl$1@dont-email.me>
Injection-Date: Tue, 20 Jul 2021 13:19:14 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="20252"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Tue, 20 Jul 2021 13:19 UTC

David Brown <david.brown@hesbynett.no> wrote:
> On 20/07/2021 13:15, John Forkosh wrote:
>> 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?
>>
>
> The best solution, when you can, is to use inline (or static inline)
> functions instead of macros. They are clearer, nicer to write, and
> safer to use.
>
> But if you can't avoid using a macro, ...

Yeah, I could avoid using a macro without any particular inconvenience,
but it's kind of got the karma of a macro.

> ... wrap the contents in a "do { ... } while (0)" loop.
> This will be executed exactly once, but avoids
> complicated interactions with calling code with conditionals.

Thanks, David. As you're probably seeing now, Ben suggested exactly
the same thing, so I guess that's the established convention,
and I'll try to get used to doing it that way.

> And I recommend you get in the habit of writing :
> if (xxx) {
> setlink(a, b, c);
> } else {
> yyy;
> }
> People vary in their opinions and styles, of course, ...

Yuk! My, but that's ugly. :) For just one statement in the
if-clause and/or else-clause, I typically wouldn't use {}'s at all.
And for just a few statements, I typically write it like
if (xxx) {
setlink(a, b, c);
getlink(d, e, f); }
else {
yyy;
zzz; }
For many statements
if (xxx) {
aaa;
bbb;
...
zzz;
} /* --- end-of-if(xxx) --- */
(and when there are many statements in the if-cluase,
I'd typically avoid an else-clause entirely)

> ... and there may be
> overriding concerns (such as matching existing code). But the use of
> brackets and indentation here means there can never be any doubts or
> ambiguities, with the structure immediately obvious to any reader and no
> concerns about whether the apparent code structure matches the actual
> structure seen by the compiler. It is a style used by people who value
> code safety and correctness higher than code compactness. (K&R call it
> "the one true brace style".)
--
John Forkosh ( mailto: j@f.com where j=john and f=forkosh )

Re: How to disambiguate macro?

<sd6jnv$hm1$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17578&group=comp.lang.c#17578

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: bc...@freeuk.com (Bart)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 14:40:10 +0100
Organization: A noiseless patient Spider
Lines: 62
Message-ID: <sd6jnv$hm1$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <sd6gqq$sjl$1@dont-email.me>
<sd6igi$jos$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 20 Jul 2021 13:40:15 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="2cf338954d2a92f6357e50d991d768bb";
logging-data="18113"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/QnKEcYIlJ0c9097TnVqmQSEnEWtnj0lM="
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:Pj0LPvd59eWIcE3fbEcgWdVBa9U=
In-Reply-To: <sd6igi$jos$1@reader1.panix.com>
X-Antivirus-Status: Clean
Content-Language: en-GB
X-Antivirus: AVG (VPS 210720-0, 20/7/2021), Outbound message
 by: Bart - Tue, 20 Jul 2021 13:40 UTC

On 20/07/2021 14:19, John Forkosh wrote:
> David Brown <david.brown@hesbynett.no> wrote:

>> And I recommend you get in the habit of writing :
>> if (xxx) {
>> setlink(a, b, c);
>> } else {
>> yyy;
>> }
>> People vary in their opinions and styles, of course, ...
>
> Yuk! My, but that's ugly. :) For just one statement in the
> if-clause and/or else-clause, I typically wouldn't use {}'s at all.

Think about when someone else needs to debug your code and wants to
insert print statements or break points.

> And for just a few statements, I typically write it like
> if (xxx) {
> setlink(a, b, c);
> getlink(d, e, f); }
> else {
> yyy;
> zzz; }

> For many statements
> if (xxx) {
> aaa;
> bbb;
> ...
> zzz;
> } /* --- end-of-if(xxx) --- */
> (and when there are many statements in the if-cluase,
> I'd typically avoid an else-clause entirely)

OK, so not only does someone need to keep in mind whether there are 1 or
N statements, there might now be 1, small N, or large N!

Which means that, when developing code and you are adding or removing
statements, you have to keep adding, removing and repositioning braces?

What happens also when you temporarily need to comment out a line; here:

if (cond)
// statement;
else

this becomes invalid syntax. (And when there is no 'else', the following
statement now becomes conditional!)

And here:

if (xxx) {
setlink(a, b, c);
// getlink(d, e, f); }

You now have an unpaired "{".

There are reasons for following guidelines for code layout...

Re: How to disambiguate macro?

<87fsw9m4qd.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17579&group=comp.lang.c#17579

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 15:36:58 +0100
Organization: A noiseless patient Spider
Lines: 56
Message-ID: <87fsw9m4qd.fsf@bsb.me.uk>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="ff971a2e694b10a43f33d9b018b8731a";
logging-data="11532"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+xxlah6KoPcZhyGqt8XCi5NunBwLVqHME="
Cancel-Lock: sha1:Zl76DC6aa+KVKlKT//b0xvEpDfo=
sha1:/RtKsTYZq7Ntlex1d20B5/pIGC0=
X-BSB-Auth: 1.f1fdf597af4af77ef761.20210720153658BST.87fsw9m4qd.fsf@bsb.me.uk
 by: Ben Bacarisse - Tue, 20 Jul 2021 14:36 UTC

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.

Re: How to disambiguate macro?

<sd6r6d$98e$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17580&group=comp.lang.c#17580

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: andreyta...@hotmail.com (Andrey Tarasevich)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 08:47:24 -0700
Organization: A noiseless patient Spider
Lines: 32
Message-ID: <sd6r6d$98e$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 20 Jul 2021 15:47:25 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="e3b3e0ced4ae803521a8ecb558b3a908";
logging-data="9486"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/ojXUCLJGeZXZjhbXoFFlU"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.12.0
Cancel-Lock: sha1:XJM/9ig6RSvPD624z7BZhgtSwL8=
In-Reply-To: <sd6b8j$498$1@reader1.panix.com>
Content-Language: en-US
 by: Andrey Tarasevich - Tue, 20 Jul 2021 15:47 UTC

On 7/20/2021 4:15 AM, John Forkosh wrote:
>
> So what's a way to define the macro that simultaneously removes
> any potential semantic confusion without introducing the necessity of
> any unpretty syntax?
>

Formally, you can simply make sure that your macro contains a /complete/
`if` statement

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

This formally solves the original issue, but opens another can of worms
because of that open `else` dangling at the end.

A somewhat better idea is to invert the logic and place the "payload"
into the `else` branch

#define setlink(ptr,nsew,link) if ( !checknode(ptr) ) ; else\
((node *)(ptr))->nsew = (node *)(link)

which is useful at times but still open to exploits.

And, of course, the de-facto standard approach is the `do { ... } while
(0)` trick already mentioned above. Its functionality is based on a
curious property of C syntax, where `do { } while (...)` happens to be
the only form of compound statement that requires a `;` at the end.

--
Best regards,
Andrey Tarasevich

Re: How to disambiguate macro?

<sd76gb$r63$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17583&group=comp.lang.c#17583

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 21:00:26 +0200
Organization: A noiseless patient Spider
Lines: 166
Message-ID: <sd76gb$r63$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <sd6gqq$sjl$1@dont-email.me>
<sd6igi$jos$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 20 Jul 2021 19:00:27 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="33fa34b8dfc966f8942913d4d5fef52a";
logging-data="27843"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+RLps3TkBMbPFdUE5kKGxhRYze5Il3IUU="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:zDCCZ+vgSzcDk0czfqsjOLzKfcg=
In-Reply-To: <sd6igi$jos$1@reader1.panix.com>
Content-Language: en-GB
 by: David Brown - Tue, 20 Jul 2021 19:00 UTC

On 20/07/2021 15:19, John Forkosh wrote:
> David Brown <david.brown@hesbynett.no> wrote:
>> On 20/07/2021 13:15, John Forkosh wrote:
>>> 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?
>>>
>>
>> The best solution, when you can, is to use inline (or static inline)
>> functions instead of macros. They are clearer, nicer to write, and
>> safer to use.
>>
>> But if you can't avoid using a macro, ...
>
> Yeah, I could avoid using a macro without any particular inconvenience,
> but it's kind of got the karma of a macro.
>

Macros don't have karma. Function-like macros are occasionally useful,
such as when you need to handle data of different types, or variadic
macros, or where a parameter to the macro can't work as a function
parameter. But if it is reasonably possible, there are many advantages
to static inline functions.

>> ... wrap the contents in a "do { ... } while (0)" loop.
>> This will be executed exactly once, but avoids
>> complicated interactions with calling code with conditionals.
>
> Thanks, David. As you're probably seeing now, Ben suggested exactly
> the same thing, so I guess that's the established convention,
> and I'll try to get used to doing it that way.

It is indeed the convention - it is the simplest way to get what you
want from a macro. (And if you think it is ugly or cumbersome, that's a
reason to prefer inline functions.)

>
>> And I recommend you get in the habit of writing :
>> if (xxx) {
>> setlink(a, b, c);
>> } else {
>> yyy;
>> }
>> People vary in their opinions and styles, of course, ...
>
> Yuk! My, but that's ugly. :) For just one statement in the
> if-clause and/or else-clause, I typically wouldn't use {}'s at all.

Many people would agree with you. And many people (not necessarily the
same people) make mistakes when writing code without brackets, or - more
often - when modifying and maintaining code that is written without the
brackets.

If you want elegant, minimal coding style, pick a different language.
If you want "cool" tight-looking code with bugs or traps for the next
person down the road, write C without style guides and with minimal
brackets, parentheses, etc. Tight coding styles are fine if everyone
involved has long experience with the language, and you are sure of
exactly what is going on at every point (such as no function-like macros
masquerading as functions).

I work with embedded systems that need to /work/. They don't get to
have bugs - bugs can cost a great deal of money, and in some cases are
safety-critical. When you want to make reliable software (in any
language), you greatly restrict the way you write the code. You care
about making the code do what it appears to do, and appear to do what it
does do - you don't care if someone thinks it is ugly. (You care
greatly about legibility, which is a different thing.) And you care
about it being utterly obvious to anyone reading the code, or making
changes to it in the future. You care about finding multiple ways to
minimise the risk of errors - and apply /all/ of them.

So you put in the brackets in an "if" - then if the enclosed statement
that looks like a function call is actually a multiple statement macro,
it still works. You wrap your multiple statement macros in a
do/while(0) loop - then if it is called from an "if" without brackets,
it still works. You use all the static error checkers and style
checkers you can so that you are warned if you've made a mistake here -
and you set your tools to mark it as an error, not just a warning. And
you have a code review so that someone else checks the style too.

Of course, using brackets for conditionals is just a minor aspect of
writing good, clear, safe code. There are many other things, many of
them more important. And there are cases where there can be do doubts
of what is going on, regardless of brackets. I am quite happy with :

if (!p) return 0;

"return" could not possibly be doing anything else here.

My rules about the enclosed statement(s) are (roughly) :

If you have the statement on a newline, indent it. And if there is
indentation, there are /always/ brackets.

If you have an "else", there are brackets. (And if you have brackets,
there are always new lines and indentations. Indents and brackets go
hand in hand.) If there are nested conditionals, there are brackets.

If you call a function, there are brackets. If you have multiple
actions, there are brackets. (Anyone using a comma operator to do
multiple things in one expression gets thrown out of the code review.)

If there is doubt, there are brackets.

> And for just a few statements, I typically write it like
> if (xxx) {
> setlink(a, b, c);
> getlink(d, e, f); }
> else {
> yyy;
> zzz; }

That's a style some people use. I don't like it, but it is better than
no brackets.

> For many statements
> if (xxx) {
> aaa;
> bbb;
> ...
> zzz;
> } /* --- end-of-if(xxx) --- */
> (and when there are many statements in the if-cluase,
> I'd typically avoid an else-clause entirely)

I don't like the inconsistency here. If you feel the need of adding an
"end-of-if" comment, your conditional is too long - split the function
up. Static functions are free. A bigger monitor is also quite
reasonably priced, if that is what it takes to be able to see the code
you are working on.

>
>> ... and there may be
>> overriding concerns (such as matching existing code). But the use of
>> brackets and indentation here means there can never be any doubts or
>> ambiguities, with the structure immediately obvious to any reader and no
>> concerns about whether the apparent code structure matches the actual
>> structure seen by the compiler. It is a style used by people who value
>> code safety and correctness higher than code compactness. (K&R call it
>> "the one true brace style".)

Re: How to disambiguate macro?

<sd76kc$r63$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17584&group=comp.lang.c#17584

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 21:02:36 +0200
Organization: A noiseless patient Spider
Lines: 68
Message-ID: <sd76kc$r63$2@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <sd6gqq$sjl$1@dont-email.me>
<sd6igi$jos$1@reader1.panix.com> <sd6jnv$hm1$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Injection-Date: Tue, 20 Jul 2021 19:02:36 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="33fa34b8dfc966f8942913d4d5fef52a";
logging-data="27843"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX198hmmOt49Eb5HiGf03ucQGAHd04tDtboo="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:HGwmS2FnibDsaa6Iy20KF5uonLA=
In-Reply-To: <sd6jnv$hm1$1@dont-email.me>
Content-Language: en-GB
 by: David Brown - Tue, 20 Jul 2021 19:02 UTC

On 20/07/2021 15:40, Bart wrote:
> On 20/07/2021 14:19, John Forkosh wrote:
>> David Brown <david.brown@hesbynett.no> wrote:
>
>>> And I recommend you get in the habit of writing :
>>>          if (xxx) {
>>>                  setlink(a, b, c);
>>>          } else {
>>>                  yyy;
>>>          }
>>> People vary in their opinions and styles, of course, ...
>>
>> Yuk! My, but that's ugly. :)  For just one statement in the
>> if-clause and/or else-clause, I typically wouldn't use {}'s at all.
>
> Think about when someone else needs to debug your code and wants to
> insert print statements or break points.
>
>> And for just a few statements, I typically write it like
>>            if (xxx) {
>>              setlink(a, b, c);
>>              getlink(d, e, f); }
>>            else {
>>              yyy;
>>              zzz; }
>
>
>> For many statements
>>            if (xxx) {
>>              aaa;
>>              bbb;
>>              ...
>>              zzz;
>>              } /* --- end-of-if(xxx) --- */
>> (and when there are many statements in the if-cluase,
>> I'd typically avoid an else-clause entirely)
>
> OK, so not only does someone need to keep in mind whether there are 1 or
> N statements, there might now be 1, small N, or large N!
>
> Which means that, when developing code and you are adding or removing
> statements, you have to keep adding, removing and repositioning braces?
>
> What happens also when you temporarily need to comment out a line; here:
>
>   if (cond)
>  //  statement;
>   else
>
> this becomes invalid syntax. (And when there is no 'else', the following
> statement now becomes conditional!)
>
> And here:
>
>             if (xxx) {
>               setlink(a, b, c);
> //              getlink(d, e, f); }
>
>
> You now have an unpaired "{".
>
> There are reasons for following guidelines for code layout...
>

We have disagreed about more than a few things in this group, Bart, but
here you have eloquently described many important points and I fully
agree with you.

Re: How to disambiguate macro?

<sd7ud2$hkh$1@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17589&group=comp.lang.c#17589

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 01:48:18 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd7ud2$hkh$1@reader1.panix.com>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk> <sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
Injection-Date: Wed, 21 Jul 2021 01:48:18 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="18065"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Wed, 21 Jul 2021 01:48 UTC

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 )

Re: How to disambiguate macro?

<sd805a$qr8$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17590&group=comp.lang.c#17590

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: andreyta...@hotmail.com (Andrey Tarasevich)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 19:18:16 -0700
Organization: A noiseless patient Spider
Lines: 18
Message-ID: <sd805a$qr8$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 21 Jul 2021 02:18:18 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="42d85c3a79cb1b8c71619f34a0fb255c";
logging-data="27496"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18ZXK7RebuKspwPi6NU1Kre"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.12.0
Cancel-Lock: sha1:x/2pBxlHzIs9JMzBB96/SO3w84o=
In-Reply-To: <sd7ud2$hkh$1@reader1.panix.com>
Content-Language: en-US
 by: Andrey Tarasevich - Wed, 21 Jul 2021 02:18 UTC

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

Re: How to disambiguate macro?

<87eebs1h4j.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17591&group=comp.lang.c#17591

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Tue, 20 Jul 2021 20:27:08 -0700
Organization: None to speak of
Lines: 39
Message-ID: <87eebs1h4j.fsf@nosuchdomain.example.com>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="3dbb069d6fac32b4b637197387ebf1ae";
logging-data="6189"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX182AUrEgrd6HSUhXBPaNStO"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:/56bcb6K41mhW+4lQU/h9hODeVY=
sha1:cHcFYlQpM+6ff7u5UY8oIiqg7VI=
 by: Keith Thompson - Wed, 21 Jul 2021 03:27 UTC

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 */

Re: How to disambiguate macro?

<sd871m$r0p$1@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17592&group=comp.lang.c#17592

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 04:15:50 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd871m$r0p$1@reader1.panix.com>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk> <sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk> <sd7ud2$hkh$1@reader1.panix.com> <87eebs1h4j.fsf@nosuchdomain.example.com>
Injection-Date: Wed, 21 Jul 2021 04:15:50 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="27673"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Wed, 21 Jul 2021 04:15 UTC

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 )

Re: How to disambiguate macro?

<sd8e2b$skd$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17593&group=comp.lang.c#17593

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 08:15:39 +0200
Organization: A noiseless patient Spider
Lines: 166
Message-ID: <sd8e2b$skd$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <sd6gqq$sjl$1@dont-email.me>
<sd6igi$jos$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 21 Jul 2021 06:15:39 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="5034648778e76de81508b6aa8e6ee000";
logging-data="29325"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18RfJuztW3PZ7ehAY3k5FSJSL1BMLvqxW4="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:e4jZ+T6Y7EDIlx7JcIJGOjVNwbY=
In-Reply-To: <sd6igi$jos$1@reader1.panix.com>
Content-Language: en-GB
X-Mozilla-News-Host: news://news.lyse.net
 by: David Brown - Wed, 21 Jul 2021 06:15 UTC

On 20/07/2021 15:19, John Forkosh wrote:
> David Brown <david.brown@hesbynett.no> wrote:
>> On 20/07/2021 13:15, John Forkosh wrote:
>>> 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?
>>>
>>
>> The best solution, when you can, is to use inline (or static inline)
>> functions instead of macros. They are clearer, nicer to write, and
>> safer to use.
>>
>> But if you can't avoid using a macro, ...
>
> Yeah, I could avoid using a macro without any particular inconvenience,
> but it's kind of got the karma of a macro.
>

Macros don't have karma. Function-like macros are occasionally useful,
such as when you need to handle data of different types, or variadic
macros, or where a parameter to the macro can't work as a function
parameter. But if it is reasonably possible, there are many advantages
to static inline functions.

>> ... wrap the contents in a "do { ... } while (0)" loop.
>> This will be executed exactly once, but avoids
>> complicated interactions with calling code with conditionals.
>
> Thanks, David. As you're probably seeing now, Ben suggested exactly
> the same thing, so I guess that's the established convention,
> and I'll try to get used to doing it that way.

It is indeed the convention - it is the simplest way to get what you
want from a macro. (And if you think it is ugly or cumbersome, that's a
reason to prefer inline functions.)

>
>> And I recommend you get in the habit of writing :
>> if (xxx) {
>> setlink(a, b, c);
>> } else {
>> yyy;
>> }
>> People vary in their opinions and styles, of course, ...
>
> Yuk! My, but that's ugly. :) For just one statement in the
> if-clause and/or else-clause, I typically wouldn't use {}'s at all.

Many people would agree with you. And many people make mistakes when
writing code without brackets, or - more often - when modifying and
maintaining code that is written without the brackets.

If you want elegant, minimal coding style, pick a different language.
If you want "cool" tight-looking code with bugs or traps for the next
person down the road, write C without style guides and with minimal
brackets, parentheses, etc. Tight coding styles are fine if everyone
involved has long experience with the language, and you are sure of
exactly what is going on at every point (such as no function-like macros
masquerading as functions).

I work with embedded systems that need to /work/. They don't get to
have bugs - bugs can cost a great deal of money, and in some cases are
safety-critical. When you want to make reliable software (in any
language), you greatly restrict the way you write the code. You care
about making the code do what it appears to do, and appear to do what it
does do - you don't care if someone thinks it is ugly. (You care
greatly about legibility, which is a different thing.) And you care
about it being utterly obvious to anyone reading the code, or making
changes to it in the future. You care about finding multiple ways to
minimise the risk of errors - and apply /all/ of them.

So you put in the brackets in an "if" - then if the enclosed statement
that looks like a function call is actually a multiple statement macro,
it still works. You wrap your multiple statement macros in a
do/while(0) loop - then if it is called from an "if" without brackets,
it still works. You use all the static error checkers and style
checkers you can so that you are warned if you've made a mistake here -
and you set your tools to mark it as an error, not just a warning. And
you have a code review so that someone else checks the style too.

Of course, using brackets for conditionals is just a minor aspect of
writing good, clear, safe code. There are many other things, many of
them more important. And there are cases where there can be do doubts
of what is going on, regardless of brackets. I am quite happy with :

if (!p) return 0;

"return" could not possibly be doing anything else here.

My rules about the enclosed statement(s) are (roughly) :

If you have the statement on a newline, indent it. And if there is
indentation, there are /always/ brackets.

If you have an "else", there are brackets. (And if you have brackets,
there are always new lines and indentations. Indents and brackets go
hand in hand.) If there are nested conditionals, there are brackets.

If you call a function, there are brackets. If you have multiple
actions, there are brackets. (Anyone using a comma operator to do
multiple things in one expression gets thrown out of the code review.)

If there is doubt, there are brackets.

> And for just a few statements, I typically write it like
> if (xxx) {
> setlink(a, b, c);
> getlink(d, e, f); }
> else {
> yyy;
> zzz; }

That's a style some people use. I don't like it, but it is better than
no brackets. Style is something that people will /never/ agree on - all
I can tell you is what /I/ see working well.

> For many statements
> if (xxx) {
> aaa;
> bbb;
> ...
> zzz;
> } /* --- end-of-if(xxx) --- */
> (and when there are many statements in the if-cluase,
> I'd typically avoid an else-clause entirely)

I don't like the inconsistency here. Pick a style, and stick to it.

If your conditional is so big you thing an "end-of-if" comment helps,
you should seriously consider re-factoring and splitting the function.
Static functions are free. (And decent sized monitors are not very
expensive either.)

>
>> ... and there may be
>> overriding concerns (such as matching existing code). But the use of
>> brackets and indentation here means there can never be any doubts or
>> ambiguities, with the structure immediately obvious to any reader and no
>> concerns about whether the apparent code structure matches the actual
>> structure seen by the compiler. It is a style used by people who value
>> code safety and correctness higher than code compactness. (K&R call it
>> "the one true brace style".)

Re: How to disambiguate macro?

<87a6mg11p9.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17594&group=comp.lang.c#17594

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: Keith.S....@gmail.com (Keith Thompson)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 02:00:18 -0700
Organization: None to speak of
Lines: 47
Message-ID: <87a6mg11p9.fsf@nosuchdomain.example.com>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com>
<87eebs1h4j.fsf@nosuchdomain.example.com>
<sd871m$r0p$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="3dbb069d6fac32b4b637197387ebf1ae";
logging-data="23782"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/i9SCWQgCSo2fSOJ5kpknP"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:sE5lGYNTa566UYgNXFGFCj8pF8I=
sha1:IbEMyZflZPLezGxM+VE18u5+X2Y=
 by: Keith Thompson - Wed, 21 Jul 2021 09:00 UTC

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 */

Re: How to disambiguate macro?

<sd8r8p$fph$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17595&group=comp.lang.c#17595

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: jameskuy...@alumni.caltech.edu (James Kuyper)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 06:00:57 -0400
Organization: A noiseless patient Spider
Lines: 11
Message-ID: <sd8r8p$fph$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 21 Jul 2021 10:00:57 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="50a49507b8d3e55c963a1da7549d1f4b";
logging-data="16177"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+S9DrHHA/V2i19tBHDNBV2QR5rbvvXUbo="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:YjUuDw4MWNvzk+e8L0NQ6wbGPvs=
In-Reply-To: <sd7ud2$hkh$1@reader1.panix.com>
Content-Language: en-US
 by: James Kuyper - Wed, 21 Jul 2021 10:00 UTC

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.

Re: How to disambiguate macro?

<sd8rbp$fph$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17596&group=comp.lang.c#17596

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: jameskuy...@alumni.caltech.edu (James Kuyper)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 06:02:33 -0400
Organization: A noiseless patient Spider
Lines: 29
Message-ID: <sd8rbp$fph$2@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com> <87eebs1h4j.fsf@nosuchdomain.example.com>
<sd871m$r0p$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 21 Jul 2021 10:02:34 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="50a49507b8d3e55c963a1da7549d1f4b";
logging-data="16177"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/zeXT9aTBSJScZnqXXa/GDBu0vEJXFAxQ="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:NDevkQO9bbEfbnqAJQDCP+Oe5OY=
In-Reply-To: <sd871m$r0p$1@reader1.panix.com>
Content-Language: en-US
 by: James Kuyper - Wed, 21 Jul 2021 10:02 UTC

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/

Re: How to disambiguate macro?

<sd8rra$f4o$1@reader1.panix.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17597&group=comp.lang.c#17597

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!weretis.net!feeder6.news.weretis.net!panix!.POSTED.panix3.panix.com!not-for-mail
From: fork...@panix.com (John Forkosh)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 10:10:50 -0000 (UTC)
Organization: PANIX Public Access Internet and UNIX, NYC
Message-ID: <sd8rra$f4o$1@reader1.panix.com>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk> <sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk> <sd7ud2$hkh$1@reader1.panix.com> <sd8r8p$fph$1@dont-email.me>
Injection-Date: Wed, 21 Jul 2021 10:10:50 -0000 (UTC)
Injection-Info: reader1.panix.com; posting-host="panix3.panix.com:166.84.1.3";
logging-data="15512"; mail-complaints-to="abuse@panix.com"
User-Agent: tin/2.4.5-20201224 ("Glen Albyn") (NetBSD/9.2 (amd64))
 by: John Forkosh - Wed, 21 Jul 2021 10:10 UTC

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 )

Re: How to disambiguate macro?

<sd8t0p$qqp$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17598&group=comp.lang.c#17598

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: bc...@freeuk.com (Bart)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 11:30:43 +0100
Organization: A noiseless patient Spider
Lines: 34
Message-ID: <sd8t0p$qqp$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com> <sd8r8p$fph$1@dont-email.me>
<sd8rra$f4o$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 21 Jul 2021 10:30:49 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="d7735f54b1c6d948185852b1a363e0ec";
logging-data="27481"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1812kqTItweuDtcicykb/rI+vvuXJTkMbY="
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:PEXx447NhcxyxVDB9JdSL0JBMLM=
In-Reply-To: <sd8rra$f4o$1@reader1.panix.com>
X-Antivirus-Status: Clean
Content-Language: en-GB
X-Antivirus: AVG (VPS 210721-0, 21/7/2021), Outbound message
 by: Bart - Wed, 21 Jul 2021 10:30 UTC

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.

Re: How to disambiguate macro?

<sd90ij$lan$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17599&group=comp.lang.c#17599

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: david.br...@hesbynett.no (David Brown)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 13:31:31 +0200
Organization: A noiseless patient Spider
Lines: 90
Message-ID: <sd90ij$lan$1@dont-email.me>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com> <sd8r8p$fph$1@dont-email.me>
<sd8rra$f4o$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 21 Jul 2021 11:31:31 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="5034648778e76de81508b6aa8e6ee000";
logging-data="21847"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+rBoCwFlPvWBpEEa1i8+6/GAIIYIDRM6E="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101
Thunderbird/68.10.0
Cancel-Lock: sha1:FSHGaYuHf671+wWj85PjQ95mxC8=
In-Reply-To: <sd8rra$f4o$1@reader1.panix.com>
Content-Language: en-GB
 by: David Brown - Wed, 21 Jul 2021 11:31 UTC

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 ? :

Re: How to disambiguate macro?

<87k0ljlvsu.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17600&group=comp.lang.c#17600

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 13:02:09 +0100
Organization: A noiseless patient Spider
Lines: 40
Message-ID: <87k0ljlvsu.fsf@bsb.me.uk>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com> <sd8r8p$fph$1@dont-email.me>
<sd8rra$f4o$1@reader1.panix.com>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="4cf7f3a355a2ef187a6fe4ebd693fd15";
logging-data="27426"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18snVrl+hxxZ/M1/SKvH/WIMoBeesVAjw8="
Cancel-Lock: sha1:aDiekhVJAE/rCUaoN0nyVGb9jos=
sha1:EcUaE1+LKdvU1J9rigvK0H+1IBs=
X-BSB-Auth: 1.16907e6a13767188702e.20210721130209BST.87k0ljlvsu.fsf@bsb.me.uk
 by: Ben Bacarisse - Wed, 21 Jul 2021 12:02 UTC

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.

Re: How to disambiguate macro?

<8735s7ls5z.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17601&group=comp.lang.c#17601

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: ben.use...@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 14:20:40 +0100
Organization: A noiseless patient Spider
Lines: 15
Message-ID: <8735s7ls5z.fsf@bsb.me.uk>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com> <sd8r8p$fph$1@dont-email.me>
<sd8rra$f4o$1@reader1.panix.com> <87k0ljlvsu.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain
Injection-Info: reader02.eternal-september.org; posting-host="4cf7f3a355a2ef187a6fe4ebd693fd15";
logging-data="27986"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/gQZXfThzgT17h2qciQZdwXSrZpdieWqI="
Cancel-Lock: sha1:vElFhifPTsjGDAM+P4N8X8OQu2E=
sha1:6otOmEi5/H74WyHWJn/V39lPb/Q=
X-BSB-Auth: 1.7bb5db02fe08980ea916.20210721142040BST.8735s7ls5z.fsf@bsb.me.uk
 by: Ben Bacarisse - Wed, 21 Jul 2021 13:20 UTC

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.

Re: How to disambiguate macro?

<sd988e$1ea5$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17602&group=comp.lang.c#17602

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!aioe.org!Puiiztk9lHEEQC0y3uUjRA.user.46.165.242.75.POSTED!not-for-mail
From: non...@add.invalid (Manfred)
Newsgroups: comp.lang.c
Subject: Re: How to disambiguate macro?
Date: Wed, 21 Jul 2021 15:42:37 +0200
Organization: Aioe.org NNTP Server
Message-ID: <sd988e$1ea5$1@gioia.aioe.org>
References: <sd6b8j$498$1@reader1.panix.com> <878s21gney.fsf@bsb.me.uk>
<sd6h5j$hng$2@reader1.panix.com> <87fsw9m4qd.fsf@bsb.me.uk>
<sd7ud2$hkh$1@reader1.panix.com> <sd8r8p$fph$1@dont-email.me>
<sd8rra$f4o$1@reader1.panix.com> <87k0ljlvsu.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Info: gioia.aioe.org; logging-data="47429"; posting-host="Puiiztk9lHEEQC0y3uUjRA.user.gioia.aioe.org"; mail-complaints-to="abuse@aioe.org";
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.12.0
Content-Language: en-US
X-Notice: Filtered by postfilter v. 0.9.2
 by: Manfred - Wed, 21 Jul 2021 13:42 UTC

On 7/21/2021 2:02 PM, Ben Bacarisse wrote:
> 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!

Just more explicit for the OP:
- This behaviour is mandated by the standard.
- This behaviour has been a key feature of the operator since the
beginning of time, so if anything is going to change in the C standard,
it's not going to be this part.

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

Also for the OP:
The *C operator* && is not commutative.
The logical AND operation is, but that's a difference between the C
operator and the logical operation.

>
> <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.
>

Pages:123
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor