Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #160087 > unrolled thread
| Started by | Oğuz <oguzismailuysal@gmail.com> |
|---|---|
| First post | 2021-04-13 22:43 -0700 |
| Last post | 2021-07-11 00:24 -0700 |
| Articles | 18 — 10 participants |
Back to article view | Back to comp.lang.c
Which side of bitwise OR is evaluated first? Oğuz <oguzismailuysal@gmail.com> - 2021-04-13 22:43 -0700
Re: Which side of bitwise OR is evaluated first? Barry Schwarz <schwarzb@delq.com> - 2021-04-14 00:04 -0700
Re: Which side of bitwise OR is evaluated first? David Brown <david.brown@hesbynett.no> - 2021-04-14 09:42 +0200
Re: Which side of bitwise OR is evaluated first? Oğuz <oguzismailuysal@gmail.com> - 2021-04-14 00:51 -0700
Re: Which side of bitwise OR is evaluated first? David Brown <david.brown@hesbynett.no> - 2021-04-14 11:25 +0200
Re: Which side of bitwise OR is evaluated first? Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-04-14 03:27 -0700
Re: Which side of bitwise OR is evaluated first? David Brown <david.brown@hesbynett.no> - 2021-04-14 13:28 +0200
Re: Which side of bitwise OR is evaluated first? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-04-14 10:31 -0700
Re: Which side of bitwise OR is evaluated first? David Brown <david.brown@hesbynett.no> - 2021-04-14 19:40 +0200
Re: Which side of bitwise OR is evaluated first? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-04-14 10:26 -0700
Re: Which side of bitwise OR is evaluated first? Richard Damon <Richard@Damon-Family.org> - 2021-04-14 07:22 -0400
Re: Which side of bitwise OR is evaluated first? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-04-14 07:54 -0700
Re: Which side of bitwise OR is evaluated first? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-04-14 14:23 -0400
Re: Which side of bitwise OR is evaluated first? scott@slp53.sl.home (Scott Lurndal) - 2021-04-14 14:33 +0000
Re: Which side of bitwise OR is evaluated first? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-04-14 13:15 -0400
Re: Which side of bitwise OR is evaluated first? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-04-14 08:06 -0700
Re: Which side of bitwise OR is evaluated first? Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2021-04-14 10:34 -0600
Re: Which side of bitwise OR is evaluated first? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-11 00:24 -0700
| From | Oğuz <oguzismailuysal@gmail.com> |
|---|---|
| Date | 2021-04-13 22:43 -0700 |
| Subject | Which side of bitwise OR is evaluated first? |
| Message-ID | <a21102b2-7c82-40d9-9549-c10a1b77247en@googlegroups.com> |
I wrote this:
fp = fopen(optarg, "r");
if (!fp || (readfrom(fp), ferror(fp)|fclose(fp)))
perror(optarg)
`readfrom' is a function of type `void' that calls `getline' until it returns -1.
The reason why I wrote it this way is that I wanted to handle all errors and close the file pointer in a single block. But I'm not sure if `ferror' is guaranteed to be called before `fclose' there, and the standard says once `fclose' is called on `fp', what `ferror(fp)' will do is unspecified or something like that.
So, should I change this or is it good (except being a bit unreadable)?
[toc] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@delq.com> |
|---|---|
| Date | 2021-04-14 00:04 -0700 |
| Message-ID | <4l4d7g5b45muvuv00aaqikoes8v2kbl8l5@4ax.com> |
| In reply to | #160087 |
On Tue, 13 Apr 2021 22:43:55 -0700 (PDT), O?uz
<oguzismailuysal@gmail.com> wrote:
>I wrote this:
>
> fp = fopen(optarg, "r");
> if (!fp || (readfrom(fp), ferror(fp)|fclose(fp)))
> perror(optarg)
>
>`readfrom' is a function of type `void' that calls `getline' until it returns -1.
>
>The reason why I wrote it this way is that I wanted to handle all errors and close the file pointer in a single block. But I'm not sure if `ferror' is guaranteed to be called before `fclose' there, and the standard says once `fclose' is called on `fp', what `ferror(fp)' will do is unspecified or something like that.
>
>So, should I change this or is it good (except being a bit unreadable)?
You could eliminate the issue with by using a variable to hold the
result of ferror, as in
if (!fp || (readfrom(fp), x=ferror(fp), fclose(fp), x))
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-04-14 09:42 +0200 |
| Message-ID | <s566dc$knc$1@dont-email.me> |
| In reply to | #160087 |
(Please try to get a proper newsreader and newsserver, rather than google groups - gg is particularly inconvenient when you have code snippets, making it hard to fix gg's broken formatting.) On 14/04/2021 07:43, Oğuz wrote: > I wrote this: > > fp = fopen(optarg, "r"); > if (!fp || (readfrom(fp), ferror(fp)|fclose(fp))) > perror(optarg) > > `readfrom' is a function of type `void' that calls `getline' until > it returns -1. > C guarantees that the left side of || and && is evaluated (including side-effects) first, and the right side is then evaluated only if necessary (depending on the first side). So the check of !fp first is safe. Similarly, the comma operator evaluates the left side first, then the right side. Other operators, such as | and &, have no such rules. The evaluation of the left and right sides are unsequenced, meaning not only that their order of evaluation is not fixed, but the can be interleaved and it can vary between runs of the code. Thus the "ferror(fp)" and "fclose(fp)" can be done in any order - and the code can in theory do half of fclose() first, then ferror(), then the rest of fclose(). > The reason why I wrote it this way is that I wanted to handle all > errors and close the file pointer in a single block. Why? > But I'm not sure > if `ferror' is guaranteed to be called before `fclose' there, and the > standard says once `fclose' is called on `fp', what `ferror(fp)' will > do is unspecified or something like that. > > So, should I change this or is it good (except being a bit > unreadable)? > IMHO, you should change it /because/ it is unreadable. The fact that you need to ask if the ordering is correct is a sure sign that you have written it in a "smart-arse" manner that requires a lot of thought to see if it does the right thing. There may be exceptional circumstances dictating your needs here, but I would write this with generous use of named local variables holding the function returns (or flags indicating their success or failure), clear conditionals, and braces so that the flow of the code is absolutely obvious at a glance, and you are sure that the /apparent/ flow is the same as a the /actual/ flow.
[toc] | [prev] | [next] | [standalone]
| From | Oğuz <oguzismailuysal@gmail.com> |
|---|---|
| Date | 2021-04-14 00:51 -0700 |
| Message-ID | <9687e80e-236f-4854-93fe-6c8f2ee78990n@googlegroups.com> |
| In reply to | #160089 |
On Wednesday, April 14, 2021 at 10:42:47 AM UTC+3, David Brown wrote: > (Please try to get a proper newsreader and newsserver, rather than > google groups - gg is particularly inconvenient when you have code > snippets, making it hard to fix gg's broken formatting.) > On 14/04/2021 07:43, Oğuz wrote: > > I wrote this: > > > > fp = fopen(optarg, "r"); > > if (!fp || (readfrom(fp), ferror(fp)|fclose(fp))) > > perror(optarg) > > > > `readfrom' is a function of type `void' that calls `getline' until > > it returns -1. > > > C guarantees that the left side of || and && is evaluated (including > side-effects) first, and the right side is then evaluated only if > necessary (depending on the first side). So the check of !fp first is > safe. Similarly, the comma operator evaluates the left side first, then > the right side. > > Other operators, such as | and &, have no such rules. The evaluation of > the left and right sides are unsequenced, meaning not only that their > order of evaluation is not fixed, but the can be interleaved and it can > vary between runs of the code. Thus the "ferror(fp)" and "fclose(fp)" > can be done in any order - and the code can in theory do half of > fclose() first, then ferror(), then the rest of fclose(). I had no idea. Thanks. > > The reason why I wrote it this way is that I wanted to handle all > > errors and close the file pointer in a single block. > Why? Purely aesthetic reasons, nothing else. I like grouping related instructions in that manner, but it sometimes make the code a real mess. > > But I'm not sure > > if `ferror' is guaranteed to be called before `fclose' there, and the > > standard says once `fclose' is called on `fp', what `ferror(fp)' will > > do is unspecified or something like that. > > > > So, should I change this or is it good (except being a bit > > unreadable)? > > > IMHO, you should change it /because/ it is unreadable. The fact that > you need to ask if the ordering is correct is a sure sign that you have > written it in a "smart-arse" manner that requires a lot of thought to > see if it does the right thing. There may be exceptional circumstances > dictating your needs here, but I would write this with generous use of > named local variables holding the function returns (or flags indicating > their success or failure), clear conditionals, and braces so that the > flow of the code is absolutely obvious at a glance, and you are sure > that the /apparent/ flow is the same as a the /actual/ flow. Yeah, I'm now convinced that I should rewrite it that way. Thanks again.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-04-14 11:25 +0200 |
| Message-ID | <s56cdc$uka$1@dont-email.me> |
| In reply to | #160090 |
On 14/04/2021 09:51, Oğuz wrote: > On Wednesday, April 14, 2021 at 10:42:47 AM UTC+3, David Brown wrote: >> (Please try to get a proper newsreader and newsserver, rather than >> google groups - gg is particularly inconvenient when you have code >> snippets, making it hard to fix gg's broken formatting.) >> On 14/04/2021 07:43, Oğuz wrote: >>> I wrote this: >>> >>> fp = fopen(optarg, "r"); >>> if (!fp || (readfrom(fp), ferror(fp)|fclose(fp))) >>> perror(optarg) >>> >>> `readfrom' is a function of type `void' that calls `getline' until >>> it returns -1. >>> >> C guarantees that the left side of || and && is evaluated (including >> side-effects) first, and the right side is then evaluated only if >> necessary (depending on the first side). So the check of !fp first is >> safe. Similarly, the comma operator evaluates the left side first, then >> the right side. >> >> Other operators, such as | and &, have no such rules. The evaluation of >> the left and right sides are unsequenced, meaning not only that their >> order of evaluation is not fixed, but the can be interleaved and it can >> vary between runs of the code. Thus the "ferror(fp)" and "fclose(fp)" >> can be done in any order - and the code can in theory do half of >> fclose() first, then ferror(), then the rest of fclose(). > > I had no idea. Thanks. > >>> The reason why I wrote it this way is that I wanted to handle all >>> errors and close the file pointer in a single block. >> Why? > > Purely aesthetic reasons, nothing else. I like grouping related > instructions in that manner, but it sometimes make the code a real mess. > >>> But I'm not sure >>> if `ferror' is guaranteed to be called before `fclose' there, and the >>> standard says once `fclose' is called on `fp', what `ferror(fp)' will >>> do is unspecified or something like that. >>> >>> So, should I change this or is it good (except being a bit >>> unreadable)? >>> >> IMHO, you should change it /because/ it is unreadable. The fact that >> you need to ask if the ordering is correct is a sure sign that you have >> written it in a "smart-arse" manner that requires a lot of thought to >> see if it does the right thing. There may be exceptional circumstances >> dictating your needs here, but I would write this with generous use of >> named local variables holding the function returns (or flags indicating >> their success or failure), clear conditionals, and braces so that the >> flow of the code is absolutely obvious at a glance, and you are sure >> that the /apparent/ flow is the same as a the /actual/ flow. > > Yeah, I'm now convinced that I should rewrite it that way. Thanks again. > My personal preference is that if code relies on knowledge of language details that some C programmers might have to look up or think about carefully, then I would consider re-arranging it. C has a set of rules for operator precedence, and for order of evaluation, which are well documented and clear. However, they are not always easily memorised, and it can be very difficult to see what complex expressions with mixed operators actually do. If it is not immediately clear at a glance, add parenthesis or break it up into multiple parts. Local variables cost nothing. The same applies to code flow. People vary about their preferences, of course, but I rarely like to have more than one piece of "do something" code (such as function calls with side-effects) in the same expression. "foo(), bar();" may have the same effect as "foo(); bar();", but I greatly prefer the second as clearer code, split on two lines. Local variables are free. Vertical space is free. Brackets and parenthesis are free. Time taken to figure out if code really does what you think it does, is not free.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2021-04-14 03:27 -0700 |
| Message-ID | <b1c7d8c0-c837-4b68-9867-b1f8ff5ab06fn@googlegroups.com> |
| In reply to | #160089 |
On Wednesday, 14 April 2021 at 08:42:47 UTC+1, David Brown wrote: [ concerning ferror(fp) & fclose(fp) ] >. Thus the "ferror(fp)" and "fclose(fp)" > can be done in any order - and the code can in theory do half of > fclose() first, then ferror(), then the rest of fclose(). > Are you sure about this?
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-04-14 13:28 +0200 |
| Message-ID | <s56jl6$iaf$1@dont-email.me> |
| In reply to | #160092 |
On 14/04/2021 12:27, Malcolm McLean wrote: > On Wednesday, 14 April 2021 at 08:42:47 UTC+1, David Brown wrote: > [ concerning ferror(fp) & fclose(fp) ] >> . Thus the "ferror(fp)" and "fclose(fp)" >> can be done in any order - and the code can in theory do half of >> fclose() first, then ferror(), then the rest of fclose(). >> > Are you sure about this? > I thought I was - but further research shows otherwise. Subexpressions to an operator like & unsequenced, and according to footnote 13 in section 5.1.2.3p3 (C18 numbering) : """ The executions of unsequenced evaluations can interleave. Indeterminately sequenced evaluations cannot interleave, but can be executed in any order. """ However, there is specific point in 6.5.2.1p10 covering function calls: """ There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function. 96) """ """ 96) In other words, function executions do not “interleave” with each other. """ So the order of the ferror() and fclose() calls is not determined, but they will not interleave as I thought they could.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-04-14 10:31 -0700 |
| Message-ID | <875z0o3h8v.fsf@nosuchdomain.example.com> |
| In reply to | #160094 |
David Brown <david.brown@hesbynett.no> writes:
[...]
> However, there is specific point in 6.5.2.1p10 covering function calls:
>
> """
> There is a sequence point after the evaluations of the function
> designator and the actual arguments but before the actual call. Every
> evaluation in the calling function (including other function calls)
> that is not otherwise specifically sequenced before or after the
> execution of the body of the called function is indeterminately
> sequenced with respect to the execution of the called function. 96)
> """
> """
> 96) In other words, function executions do not “interleave” with each other.
> """
>
> So the order of the ferror() and fclose() calls is not determined, but
> they will not interleave as I thought they could.
Some day I'll learn to read the whole thread before posting.
<Aragorn>But it is not this day!</Aragorn>
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-04-14 19:40 +0200 |
| Message-ID | <s579e4$qe0$1@dont-email.me> |
| In reply to | #160101 |
On 14/04/2021 19:31, Keith Thompson wrote: > David Brown <david.brown@hesbynett.no> writes: > [...] >> However, there is specific point in 6.5.2.1p10 covering function calls: >> >> """ >> There is a sequence point after the evaluations of the function >> designator and the actual arguments but before the actual call. Every >> evaluation in the calling function (including other function calls) >> that is not otherwise specifically sequenced before or after the >> execution of the body of the called function is indeterminately >> sequenced with respect to the execution of the called function. 96) >> """ >> """ >> 96) In other words, function executions do not “interleave” with each other. >> """ >> >> So the order of the ferror() and fclose() calls is not determined, but >> they will not interleave as I thought they could. > > Some day I'll learn to read the whole thread before posting. > > <Aragorn>But it is not this day!</Aragorn> > And one day, I'll learn to double-check in the standards before posting - but not today for me either! (Thanks to Malcolm for questioning me and encouraging me to check. It was better for me to find it out myself instead of always relying on Keith, James, Ben and the others to correct my errors.)
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-04-14 10:26 -0700 |
| Message-ID | <87a6q03hgi.fsf@nosuchdomain.example.com> |
| In reply to | #160089 |
David Brown <david.brown@hesbynett.no> writes:
> (Please try to get a proper newsreader and newsserver, rather than
> google groups - gg is particularly inconvenient when you have code
> snippets, making it hard to fix gg's broken formatting.)
>
> On 14/04/2021 07:43, Oğuz wrote:
>> I wrote this:
>>
>> fp = fopen(optarg, "r");
>> if (!fp || (readfrom(fp), ferror(fp)|fclose(fp)))
>> perror(optarg)
>>
>> `readfrom' is a function of type `void' that calls `getline' until
>> it returns -1.
>>
>
> C guarantees that the left side of || and && is evaluated (including
> side-effects) first, and the right side is then evaluated only if
> necessary (depending on the first side). So the check of !fp first is
> safe. Similarly, the comma operator evaluates the left side first, then
> the right side.
>
> Other operators, such as | and &, have no such rules. The evaluation of
> the left and right sides are unsequenced, meaning not only that their
> order of evaluation is not fixed, but the can be interleaved and it can
> vary between runs of the code. Thus the "ferror(fp)" and "fclose(fp)"
> can be done in any order - and the code can in theory do half of
> fclose() first, then ferror(), then the rest of fclose().
Function calls cannot be interleaved like that. However, standard
library calls can be implemented as macros. And in any case calling
ferror(fp) after close(fp) has undefined behavior.
N1570 6.5.2.2p10:
There is a sequence point after the evaluations of the function
designator and the actual arguments but before the actual
call. Every evaluation in the calling function (including other
function calls) that is not otherwise specifically sequenced
before or after the execution of the body of the called function
is indeterminately sequenced with respect to the execution of
the called function.
and a footnote:
In other words, function executions do not ‘‘interleave’’ with each other.
[...]
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <Richard@Damon-Family.org> |
|---|---|
| Date | 2021-04-14 07:22 -0400 |
| Message-ID | <LfAdI.1200$Qf2.110@fx38.iad> |
| In reply to | #160087 |
On 4/14/21 1:43 AM, Oğuz wrote: > I wrote this: > > fp = fopen(optarg, "r"); > if (!fp || (readfrom(fp), ferror(fp)|fclose(fp))) > perror(optarg) > > `readfrom' is a function of type `void' that calls `getline' until it returns -1. > > The reason why I wrote it this way is that I wanted to handle all errors and close the file pointer in a single block. But I'm not sure if `ferror' is guaranteed to be called before `fclose' there, and the standard says once `fclose' is called on `fp', what `ferror(fp)' will do is unspecified or something like that. > > So, should I change this or is it good (except being a bit unreadable)? > C does NOT provide any promise as to the order of evaluation for most operators. || and && and , are the exceptions that come to mind that explicitly will evaluate the first and then the second, and for || and && the second is only evaluated if its value is needed, so for || only if the first value was 'false', and for && only if the first value was 'true'
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-04-14 07:54 -0700 |
| Message-ID | <86a6q0j4qs.fsf@linuxsc.com> |
| In reply to | #160093 |
Richard Damon <Richard@Damon-Family.org> writes: > C does NOT provide any promise as to the order of evaluation for most > operators. > > || and && and , are the exceptions that come to mind that explicitly > will evaluate the first and then the second, and for || and && the > second is only evaluated if its value is needed, so for || only if the > first value was 'false', and for && only if the first value was 'true' Of course the one other case is the ?: operator, which always evalutes the first operand first, completely, and then evaluates either the second or third operand after that. (C++ has a bunch of other cases, on which I'm not completely sure of which ones or when they came into effect exactly.)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-04-14 14:23 -0400 |
| Message-ID | <s57bva$e2h$1@dont-email.me> |
| In reply to | #160093 |
In the past, when using Thunderbird to view a newsgroup, the Reply button would post a response to the group. If you wanted to sent a message only to the author, you had to do something more complicated. Now, the Reply button sends the message to the author, and there's a separate Followup button for sending it to the newsgroup. This is about the fifth time I've sent a reply to the author when I intended it to go to the newsgroup. Sorry! On 4/14/21 7:22 AM, Richard Damon wrote: ... > C does NOT provide any promise as to the order of evaluation for most > operators. > > || and && and , are the exceptions that come to mind that explicitly > will evaluate the first and then the second, and for || and && the > second is only evaluated if its value is needed, so for || only if the > first value was 'false', and for && only if the first value was 'true' Specifically, "... The value computations of the operands of an operator are sequenced before the value computation of the result of the operator." (6.5p1) "... Except as specified later, side effects and value computations of subexpressions are unsequenced." (6.5p3). Places where it is "specified later" include all three of the cases you mentioned, but also for the conditional and comma operators. There are also some sequencing guarantees that do not involve sub-expressions: function calls are guaranteed to be sequenced after the function designator expression, and after evaluations of all of their argument expressions. Thus, if f() returns a pointer to a function, in the expression f()(g(), h()), the evaluations of f(), g(), and h() are unsequenced relative to each other, but all three are sequenced before execution of the function pointed at by f()'s return value. For those operators which have the side effect of changing the value stored in an object (++, --, =, and compound assignment), that side effect is sequenced after the value computations of the sub-expression(s). It is NOT guaranteed to be sequenced after their side-effects.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-04-14 14:33 +0000 |
| Message-ID | <O2DdI.1260$RC2.686@fx27.iad> |
| In reply to | #160087 |
=?UTF-8?B?T8SfdXo=?= <oguzismailuysal@gmail.com> writes: >I wrote this: > > fp =3D fopen(optarg, "r"); > if (!fp || (readfrom(fp), ferror(fp)|fclose(fp))) > perror(optarg) > >`readfrom' is a function of type `void' that calls `getline' until it retur= >ns -1. > >The reason why I wrote it this way is that I wanted to handle all errors an= >d close the file pointer in a single block. But I'm not sure if `ferror' is= > guaranteed to be called before `fclose' there, and the standard says once = >`fclose' is called on `fp', what `ferror(fp)' will do is unspecified or som= >ething like that. > >So, should I change this or is it good (except being a bit unreadable)? "||" is _not_ a bitwise operator. It's called 'conditional-or', and the semantics include not executing the right-most part if the leftmost part is true. It's more common to write: if (fp && readfrom...)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-04-14 13:15 -0400 |
| Message-ID | <s5780a$g96$1@dont-email.me> |
| In reply to | #160095 |
On 4/14/21 10:33 AM, Scott Lurndal wrote: > =?UTF-8?B?T8SfdXo=?= <oguzismailuysal@gmail.com> writes: ... >> if (!fp || (readfrom(fp), ferror(fp)|fclose(fp))) ... > "||" is _not_ a bitwise operator. It's called 'conditional-or', and > the semantics include not executing the right-most part if the leftmost > part is true. He's not referring to the || near the beginning of that line, but to the | near the end of the same line.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-04-14 08:06 -0700 |
| Message-ID | <8635vsj46u.fsf@linuxsc.com> |
| In reply to | #160087 |
Oğuz <oguzismailuysal@gmail.com> writes:
> I wrote this:
>
> fp = fopen(optarg, "r");
> if (!fp || (readfrom(fp), ferror(fp)|fclose(fp)))
> perror(optarg)
>
> `readfrom' is a function of type `void' that calls `getline' until
> it returns -1.
>
> The reason why I wrote it this way is that I wanted to handle all
> errors and close the file pointer in a single block. But I'm not
> sure if `ferror' is guaranteed to be called before `fclose' there,
> and the standard says once `fclose' is called on `fp', what
> `ferror(fp)' will do is unspecified or something like that.
>
> So, should I change this or is it good (except being a bit
> unreadable)?
Two comments.
One, don't listen to the advice of "experts" who say something
is or is not readable. Instead try writing the code several
different ways and pick the one that best expresses what it
is you want to say.
Two, for what you're doing here I would be inclined to try something
like this:
FILE *fp = fopen( optarg, "r" );
int read_bad = fp ? readfrom( fp ), ferror( fp ) : 0;
int close_bad = fp ? fclose( fp ) : 0;
if( !fp || read_bad || close_bad ) perror( optarg );
Written this way I find it easy to see at a glance what the code is
trying to do, and what the condition is to control whether an error
message should be printed.
If that approach works for you, great. The key though is to look
for a way of writing that most closely expresses what it is you
want to say.
[toc] | [prev] | [next] | [standalone]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2021-04-14 10:34 -0600 |
| Message-ID | <1bv98ox1ts.fsf@pfeifferfamily.net> |
| In reply to | #160097 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes: > Oğuz <oguzismailuysal@gmail.com> writes: >> >> So, should I change this or is it good (except being a bit >> unreadable)? > > Two comments. > > One, don't listen to the advice of "experts" who say something > is or is not readable. Instead try writing the code several > different ways and pick the one that best expresses what it > is you want to say. Note that the OP himself described it as unreadable. I'd say any time the author of the code regards it as unreadable, we should take him at his word (for the record, I agree with him here).
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-07-11 00:24 -0700 |
| Message-ID | <86eec58ga2.fsf@linuxsc.com> |
| In reply to | #160098 |
Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes: > Tim Rentsch <tr.17687@z991.linuxsc.com> writes: > >> O?uz <oguzismailuysal@gmail.com> writes: >> >>> So, should I change this or is it good (except being a bit >>> unreadable)? >> >> Two comments. >> >> One, don't listen to the advice of "experts" who say something >> is or is not readable. Instead try writing the code several >> different ways and pick the one that best expresses what it >> is you want to say. > > Note that the OP himself described it as unreadable. I'd say any time > the author of the code regards it as unreadable, we should take him at > his word (for the record, I agree with him here). Obviously the code was not unreadable, since many people here were able to read it without too much difficulty. The author too was, rather obviously, able to read it. Some people might believe that some other, unspecified, people would have trouble reading the code, but that doesn't make it unreadable. If you were able to read the code then I don't know what you mean when you say the code is unreadable, but certainly you don't mean literally that.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web