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 | 11 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 3 of 3 — ← Prev page 1 2 [3]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-08-14 13:37 -0700 |
| Subject | Re: OT: possessive adjectives |
| Message-ID | <865yw7yd86.fsf@linuxsc.com> |
| In reply to | #162038 |
Manfred <noname@add.invalid> writes: > On 7/21/2021 11:24 PM, James Kuyper wrote: > > Sorry about the grammar nit-picking, but... > >> As others have pointed out, that's explicitly not the case in C, >> and there's lots of code that relies upon that fact in order to >> achieve it's desired effects. > > The expression "it's" is a contraction for "it is", and it doesn't > make sense here. What you mean here is "its", which is the proper > possessive adjective to be used in this sentence. Confusing the > two expressions would be the same as confusing "they're" and > "their". > > [...] > >> It's guaranteed to work by the standard, deliberately with the >> intent of > > You got "it's" right here... > >> allowing developers to rely upon that fact, and most C programmers >> have written code that relies upon that fact for it's successful >> execution. > > ... but not here either > >> Incidentally, the same is true of C++ - and a gratuitous >> incompatibly between C and C++ goes against the official policies >> of both the C committee and the C++ committee. > > Sorry for patronizing, but your posts usually read fairly correct, > so I thought this remark might not be like the proverbial drop in > an ocean in your case - besides, I have a kind of allergy to > non-compiling sentences (even if English is not my native > language, and I make mistakes myself) It may help to remember that the same rule applies to all personal pronouns: an apostrophe always indicates a contraction with "am", "is" or "are" - I am, we are - I'm, we're you are - you're he is, she is, it is, they are - he's, she's, it's, they're and there is never an apostrophe in the possessive form of a personal pronoun - my, our your his, hers, its, their
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-08-14 13:58 -0700 |
| Message-ID | <861r6vyc99.fsf@linuxsc.com> |
| In reply to | #162005 |
John Forkosh <forkosh@panix.com> writes:
> 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.
In cases like this one I usually find an expressional form works
better than a statement form, and ?: better than && (unless of
course the second part of the && is also a predicate and the
overall value is important, in which case it can depend on the
subexpressions involved).
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-07-20 14:50 +0200 |
| Message-ID | <sd6gqq$sjl$1@dont-email.me> |
| In reply to | #161988 |
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".)
[toc] | [prev] | [next] | [standalone]
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-07-20 13:19 +0000 |
| Message-ID | <sd6igi$jos$1@reader1.panix.com> |
| In reply to | #161990 |
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 )
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-07-20 14:40 +0100 |
| Message-ID | <sd6jnv$hm1$1@dont-email.me> |
| In reply to | #161993 |
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...
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-07-20 21:02 +0200 |
| Message-ID | <sd76kc$r63$2@dont-email.me> |
| In reply to | #161994 |
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.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-07-20 21:00 +0200 |
| Message-ID | <sd76gb$r63$1@dont-email.me> |
| In reply to | #161993 |
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".)
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-07-21 08:15 +0200 |
| Message-ID | <sd8e2b$skd$1@dont-email.me> |
| In reply to | #161993 |
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".)
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-08-14 23:17 -0700 |
| Message-ID | <86wnonw7sz.fsf@linuxsc.com> |
| In reply to | #161993 |
John Forkosh <forkosh@panix.com> writes:
> 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. And for just a few statements, I typically write it like
> if (xxx) {
> setlink(a, b, c);
> getlink(d, e, f); }
> else {
> yyy;
> zzz; }
Despite your visceral reaction, the layout you suggest here is
objectively inferior along at least one important axis. Studies
of various rules for bracketing layout have found that lining up
closing brackets (which are braces in this case) with the start
of their corresponding opening lines (ie, like the quoted example
recommendation) gives the lowest error rates of all the layout
styles looked at (including the "lisp style" layout you suggest).
The layout you prefer has higher error rates than the "ugly"
layout you dislike. I think any developer who is serious about
writing good code would want to follow a layout style that has
lower error rates, whatever their personal reactions might be.
[toc] | [prev] | [next] | [standalone]
| From | John Forkosh <forkosh@panix.com> |
|---|---|
| Date | 2021-07-20 12:51 +0000 |
| Message-ID | <sd6grr$hng$1@reader1.panix.com> |
| In reply to | #161988 |
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 )
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-20 08:47 -0700 |
| Message-ID | <sd6r6d$98e$1@dont-email.me> |
| In reply to | #161988 |
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
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.c
csiph-web