Recommended style

M

Mike Wahler

Bonj said:
Neither:
fp = fopen("xyz.txt", "r");
if (fp == NULL) {
...
}
is nearly right, but that's java style. Since your question is titled
'Recommended style', the correct style is
fp = fopen("xyz.txt", "r");
if (fp == NULL)
{
...
}

is correct, but if ... is only one line, then I prefer just
fp = fopen("xyz.txt", "r")
if(fp == NULL)
...

or better still
if(fopen("xyz.txt", "r") == NULL) ...

And now how will you refer to the stream?

They both will work, but if(!fp) is less explicit,

IMO it's quite explicit. A test for true/false (zero/nonzero).
as it's not actually a
boolean value you're testing, it's a returned handle, and you're testing
whether it's NULL or not.

You're testing whether 'fp', after being converted to 'int',
is zero or not.

-Mike
 
K

Keith Thompson

Mike Wahler said:
And now how will you refer to the stream?



IMO it's quite explicit. A test for true/false (zero/nonzero).


You're testing whether 'fp', after being converted to 'int',
is zero or not.

There's no conversion to int. The unary '!' operator tests whether
its operand compares equal to 0. For a pointer, comparison to 0 is
comparison to a null pointer constant.
 
M

Mike Wahler

Keith Thompson said:
There's no conversion to int. The unary '!' operator tests whether
its operand compares equal to 0. For a pointer, comparison to 0 is
comparison to a null pointer constant.

But what is the type of the expression !fp?

I was thinking in the wider context of 'if's (full)
conditional expression itself, and not the not :) operator. If
it's not already type 'int', is there a conversion or not?

e.g.

FILE *f = 0;

if(f) /* does this compare a 'FILE*' or 'int' object with zero? */
;

-Mike
 
H

Herbert Rosenau

But what is the type of the expression !fp?

The comparion is tone with the type of the variable (here a pointer to
FILE whatever that may be. The result is an int.
I was thinking in the wider context of 'if's (full)
conditional expression itself, and not the not :) operator. If
it's not already type 'int', is there a conversion or not?

There is no conversion other than the implicit 0 gets converted to be
a null pointer constant. The result is generated as of type int.
e.g.

FILE *f = 0;

if(f) /* does this compare a 'FILE*' or 'int' object with zero? */
;

Comparion is in type of the variable. Result is generated in type of
int.

if (x) or in long if (x == 0)
is falling into 3 steps
1. x == (type of x)0; /* compare given variable with (type of x)0 */
2. if x is equal to (type of x)0 then (int)1 is generated, else (int)0
is generated.
3. conditional branch checks the result of the comparsion.

if (!x) or in long if (x != 0)
exchanges only the generated value.

It is on the implementation to suppress the explicite generation of
(int)0/1 and use processor flags of the comparsion or simply use a
test instruction. Depending on the instruction set it may even do
another optimision step and use an test/branch instruction. In no case
a conversation is needed or even done.

The same is with the ?: operator - except that the explicite 0/1 must
be generated when the result is needed for more than only to
distinguish the both possible results.



--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
 
K

Keith Thompson

Mike Wahler said:
But what is the type of the expression !fp?

It's of type int.

C99 6.5.3.3p5:

The result of the logical negation operator ! is 0 if the value of
its operand compares unequal to 0, 1 if the value of its operand
compares equal to 0. The result has type int. The expression !E
is equivalent to (0==E).
I was thinking in the wider context of 'if's (full)
conditional expression itself, and not the not :) operator. If
it's not already type 'int', is there a conversion or not?

e.g.

FILE *f = 0;

if(f) /* does this compare a 'FILE*' or 'int' object with zero? */
;

C99 6.8.4.1 p1-2:

Constraints

The controlling expression of an if statement shall have scalar type.

Semantics

In both forms, the first substatement is executed if the
expression compares unequal to 0. In the else form, the second
substatement is executed if the expression compares equal to 0.

Scalar types include arithmetic and pointer types.

So in

if (f) ...

the controlling expression has type FILE*. In

if (!f) ...

the operand of the "!" has type FILE*, and the controlling expression
has type int.
 
M

Michael Mair

Herbert said:
[...]

or better still
if(fopen("xyz.txt", "r") == NULL) ...

And now how will you refer to the stream?




They both will work, but if(!fp) is less explicit,

IMO it's quite explicit. A test for true/false (zero/nonzero).


as it's not actually a
boolean value you're testing, it's a returned handle, and you're
testing

whether it's NULL or not.

You're testing whether 'fp', after being converted to 'int',
is zero or not.

There's no conversion to int. The unary '!' operator tests whether
its operand compares equal to 0. For a pointer, comparison to 0 is
comparison to a null pointer constant.

But what is the type of the expression !fp?


The comparion is tone with the type of the variable (here a pointer to
FILE whatever that may be. The result is an int.

I was thinking in the wider context of 'if's (full)
conditional expression itself, and not the not :) operator. If
it's not already type 'int', is there a conversion or not?


There is no conversion other than the implicit 0 gets converted to be
a null pointer constant. The result is generated as of type int.

e.g.

FILE *f = 0;

if(f) /* does this compare a 'FILE*' or 'int' object with zero? */
;


Comparion is in type of the variable. Result is generated in type of
int.

if (x) or in long if (x == 0)

if (x) is equivalent to if (x != 0)
is falling into 3 steps
1. x == (type of x)0; /* compare given variable with (type of x)0 */
2. if x is equal to (type of x)0 then (int)1 is generated, else (int)0
is generated.
3. conditional branch checks the result of the comparsion.

if (!x) or in long if (x != 0)

if (!x) is equivalent to if (x == 0)
exchanges only the generated value.

It is on the implementation to suppress the explicite generation of
(int)0/1 and use processor flags of the comparsion or simply use a
test instruction. Depending on the instruction set it may even do
another optimision step and use an test/branch instruction. In no case
a conversation is needed or even done.

The same is with the ?: operator - except that the explicite 0/1 must
be generated when the result is needed for more than only to
distinguish the both possible results.

Cheers
Michael
 
M

Michael Mair

Herbert said:
No, it's not, it is highly different.

Don't be ridiculous.

-----------------------
#include <stdio.h>

int main (void)
{
double f = 0.0;
char *cp = 0;
int i = 0;

if (!i)
puts("!i");
if (i==0)
puts("i==0");
if (!cp)
puts("!cp");
if (cp==0)
puts("cp==0");
if (!f)
puts("!f");
if (f==0)
puts("f==0");

return 0;
}
-----------------------

gives me:
!i
i==0
!cp
cp==0
!f
f==0


Cheers
Michael
 
S

Stephen Sprunk

Herbert Rosenau said:
No, it's not, it is highly different.

It is?

According to N869 6.5.3.3(5), they are equivalent:

"The result of the logical negation operator ! is 0 if the value of its
operand compares unequal to 0, 1 if the value of its operand compares equal
to 0. The result has type int. The expression !E is equivalent to (0==E). "

S
 
V

vir

Mike said:
Probably a troll. Note the OP's "name".
What's wrong with the name?

This style is to be used for a functions allocating several resources...
Think of

int foo (int len)
{
FILE *f1p = NULL, *f2p = NULL;
char *s = NULL;
int res = -1;

f1p = fopen (fn, fmode);
if (!f1p) {
error ();
goto fail;
}
f2p = fopen (fn, fmode);
if (!f2p) {
error ();
goto fail;
}
s = malloc (len);
if (!s) {
error ();
goto fail;
}
/*
...
Some valuable actions
...
*/
res = 0
fail:
free (s);
if (!f2p)
fclose (f2p);
if (!f1p)
fclose (f1p);
return res;
}

Cascaded function calls seems to be less readable then one function.
 
M

Mike Wahler

Herbert Rosenau said:
No, it's not, it is highly different.

Really?

ISO 9899:1999

6.5.3.3 Unary arithmetic operators

5 The result of the logical negation operator ! is 0
if the value of its operand compares unequal to 0,
1 if the value of its operand compares equal to 0.
The result has type int. The expression !E is
equivalent to (0==E).


-Mike
 
A

Allin Cottrell

Lawrence Kirby quoted:

and commented
That's a clear, concise C idiom, but please locate your space bar.

LK again quoted:

and commented:
Whereas that's just contorted. The point of space is to help the eye see
the natural grouping. Put space around everything and you're no better of
than not using spaces at all, perhaps worse.

Agreed, absolutely. If I were writing the first of these examples I
would write

if ((fp = fopen(filename, "mode")) == NULL)

and if I were writing the second,

if (NULL == (fp = fopen(filename, mode))) {

BUT... if I were writing for comprehensibility I would eschew both
and write:

fp = fopen(filename, "mode");
if (fp == NULL) {
/* respond to error condition */

There's just too great an opportunity for error in the "cutesy"
versions of this code, which roll the basic assignment into the
detection of an error condition. The immature programmer thinks,
"Look how smart I am, how many things I can do at once!". The
mature programmer thinks, "Let's do one thing at a time, in such
a way that it's quite transparent what we're doing; and let's
get it RIGHT."

IMO.

Allin Cottrell
 
M

Michael Wojcik

This style is to be used for a functions allocating several resources...
Think of

int foo (int len)
{
FILE *f1p = NULL, *f2p = NULL;
char *s = NULL;
int res = -1;

f1p = fopen (fn, fmode);
if (!f1p) {
error ();
goto fail;
}
...
fail:
free (s);
if (!f2p)
fclose (f2p);
if (!f1p)
fclose (f1p);
return res;
}

I also use this single-point-of-return style (though I employ it
slightly differently) in many cases, and consider it the most
prominent excuse for employing goto, as those who remember our
most recent "goto" flame war know. However, note that
if (!f2p)
fclose (f2p);
if (!f1p)
fclose (f1p);

should be

if (f2p)
fclose (f2p);
if (f1p)
fclose (f1p);

since obviously you want to call fclose only if the FILE* variable
is NOT null. And that, I suppose, demonstrates that correctness
still trumps style.

(Personally, I wish the committee had defined behavior for null
arguments for fclose and some of the other functions, as they did
for free, if only to get rid of those guard if's. But we have the
language we have.)
 
E

Eric Sosman

Victor said:
I usually use this:

{
fp = fopen (fn, fmode);
if (!fp) {
error ();
goto fail;
}
rc = foo (fp);
fail:
if (!fp)
fclose (fp);
}

Stylish, indeed! It verges upon the elegant! There
is, however, one tiny drawback: It's wrong.

"Other than that, Mrs. Lincoln, what did you think
of the play?"
 
B

Ben Pfaff

Eric Sosman said:
Stylish, indeed! It verges upon the elegant! There
is, however, one tiny drawback: It's wrong.

It can be made correct by deleting one character.
 
E

Eric Sosman

Ben said:
It can be made correct by deleting one character.

Or by repeating it, if "deleting a character" is
too gruesome in the context of the play (a remark your
good taste, er, deleted ...)

This sort of mistake is, I think, a good reason
to prefer `x == 0' (or `0 == x' if a backward-thinking
person you are, young Skywalker) over `!x' when `x'
isn't "obviously boolean." I particularly dislike

if (!strcmp(password, "drowssap"))

.... which tests for equality but appears on a hasty
reading to do the opposite.
 
V

vir

Michael said:
I also use this single-point-of-return style (though I employ it
slightly differently) in many cases, and consider it the most
prominent excuse for employing goto, as those who remember our
most recent "goto" flame war know.
I havn't read the thread about goto. But if I get read of goto statement
I'll need an exception mechanism in C...
However, note that




should be

if (f2p)
fclose (f2p);
if (f1p)
fclose (f1p);

since obviously you want to call fclose only if the FILE* variable
is NOT null.
Yes, sorry for this mistake.
And that, I suppose, demonstrates that correctness
still trumps style.

(Personally, I wish the committee had defined behavior for null
arguments for fclose and some of the other functions, as they did
for free, if only to get rid of those guard if's. But we have the
language we have.)
Agread. In my own code I allways write destructors accepting invalid
value (NULL in most cases).
 
P

pete

Andrey said:
It is a matter of a personal preference and/or coding standard.

Personally, I leave out explicit comparison for values with pronounced
'boolean' semantics only. All other values require explicit comparison
in my book. That would mean that I'd choose the first variant.

Me too.
 
M

Michael Wojcik

This sort of mistake is, I think, a good reason
to prefer `x == 0' (or `0 == x' if a backward-thinking
person you are, young Skywalker) over `!x' when `x'
isn't "obviously boolean."

I'm not convinced that would significantly reduce this sort of error.
I strongly doubt it would for me (though I can't recall having made
this particular mistake; doesn't mean I haven't, but it hasn't happened
often or recently enough for me to remember). I don't find the
comparison with an explicit zero any more readable than the logical-
negation one, or see any other reason why it might discourage error.

But, of course, YMMV.
I particularly dislike

if (!strcmp(password, "drowssap"))

... which tests for equality but appears on a hasty
reading to do the opposite.

With this, on the other hand, I agree. Inverted strcmp sense errors
are one of the more common sort I find in others' code. I don't
remember making one myself since I adopted Peter van der Linden's
macro, which I think does improve readability significantly. For
example:

#define MySTRCMP(s1, op, s2) (strcmp(s1, s2) op 0)
if (MySTRCMP(password, ==, "drowssap"))

Inlining the operator brings string comparisons syntactically closer
to their numeric cousins.

--
Michael Wojcik (e-mail address removed)

An intense imaginative activity accompanied by a psychological and moral
passivity is bound eventually to result in a curbing of the growth to
maturity and in consequent artistic repetitiveness and stultification.
-- D. S. Savage
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,159
Messages
2,570,883
Members
47,415
Latest member
SharonCran

Latest Threads

Top