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


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

Which side of bitwise OR is evaluated first?

Started byOğuz <oguzismailuysal@gmail.com>
First post2021-04-13 22:43 -0700
Last post2021-07-11 00:24 -0700
Articles 18 — 10 participants

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


Contents

  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

#160087 — Which side of bitwise OR is evaluated first?

FromOğuz <oguzismailuysal@gmail.com>
Date2021-04-13 22:43 -0700
SubjectWhich 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]


#160088

FromBarry Schwarz <schwarzb@delq.com>
Date2021-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]


#160089

FromDavid Brown <david.brown@hesbynett.no>
Date2021-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]


#160090

FromOğuz <oguzismailuysal@gmail.com>
Date2021-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]


#160091

FromDavid Brown <david.brown@hesbynett.no>
Date2021-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]


#160092

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2021-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]


#160094

FromDavid Brown <david.brown@hesbynett.no>
Date2021-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]


#160101

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-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]


#160102

FromDavid Brown <david.brown@hesbynett.no>
Date2021-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]


#160100

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-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]


#160093

FromRichard Damon <Richard@Damon-Family.org>
Date2021-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]


#160096

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-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]


#160103

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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]


#160095

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-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]


#160099

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-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]


#160097

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-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]


#160098

FromJoe Pfeiffer <pfeiffer@cs.nmsu.edu>
Date2021-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]


#161866

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-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