Is this C program doing what it is supposed to do ?

G

Geoff

Why? I've read several other followups in this thread, and I
haven't seen you provide any supporting arguments for this.

at_beginning is treated as a boolean. It would make sense to declare it
as bool or _Bool if the compiler supports it. Why is an explicit
comparison against 1 better than a simple test of the variable?

"if (at_beginning)" expresses the intent more clearly than
"if (at_beginning == 1)". And since "==" yields a logically boolean
result, why stop at one "=="; why not write
"if ((at_beginning == 1) == 1)"?

In this particular case, at_beginning can only have the value 0 or
1, but of course any non-zero value is treated as true. What if,
in a later version of the program, at_beginning is assigned the
result of one of the is*() functions?


I presume there's some reason behind your reaction, but I honestly
can't think of what it might be. Yes, the OP made an "=" vs. "=="
error. Surely the solution is to avoid making such errors --
which, I think, are no more likely with the suggested change than
without it.

I wouldn't call it appalling but I would call it idiomatic and
somewhat dangerous if it were to appear in an introductory C textbook.
Far from being easily read, it sets the beginner back on his chair
with a "Woah, what's going on here?"

The insistence that this idiom is preferable calls into question why
no one has suggested replacing

line += 1;

with

line++;

Furthermore, as pertains to the OP's text, this program has formed the
basis of another program regarding checksum, posted here.
<c27675a6-22a4-4432-9481-6a3618dbe362@glegroupsg2000goo.googlegroups.com>

Had the OP implemented the change Ben suggested, the program would not
have been modifiable from this:

if(ch == '\n')
at_beginning = 1;

to this:

if(ch == '\n'){
at_beginning = 1;
printf("Checksum: %d\n", checksum);
checksum = -1;
}

So from a maintenance standpoint, Ben's idiom is "less maintainable"
in this context.
 
B

Ben Bacarisse

Geoff said:
I wouldn't call it appalling but I would call it idiomatic and
somewhat dangerous if it were to appear in an introductory C textbook.
Far from being easily read, it sets the beginner back on his chair
with a "Woah, what's going on here?"

I am not so sure about that. Initial puzzlement is an almost universal
reaction to many programming constructs if one is learning programming
for the first time. After that, what is puzzling is largely determined
by what you've seen up to that point. A student who learns a functional
language first and then C will probably have no trouble at all with
capturing the value of ch == '\n' in a variable.

Incidentally, I've seen (and used) over years two styles of for learning
either programming or a new language. One uses a sort of "dumbing down"
early on: we'll do it this way for now but later on you'll see the
idiomatic way to write it. The other takes the bull by the horns and
uses whatever is the best notation. This forces the teacher to be much
more careful about choosing examples, but I much refer it in the end --
both as a student and as a teacher.
The insistence that this idiom is preferable calls into question why
no one has suggested replacing

BTW, no one insisted! I said "and here I'd write" (followed by a
reason). I could hardly have been less insistent.
line += 1;

with

line++;

Furthermore, as pertains to the OP's text, this program has formed the
basis of another program regarding checksum, posted here.
<c27675a6-22a4-4432-9481-6a3618dbe362@glegroupsg2000goo.googlegroups.com>

Had the OP implemented the change Ben suggested, the program would not
have been modifiable from this:

if(ch == '\n')
at_beginning = 1;

to this:

if(ch == '\n'){
at_beginning = 1;
printf("Checksum: %d\n", checksum);
checksum = -1;
}

So from a maintenance standpoint, Ben's idiom is "less maintainable"
in this context.

Not at all. The OP need only test the assignment. I was suggesting
this for the original:

while ((ch = getchar()) != EOF) {
if (at_beginning)
printf("%d ", ++line);
putchar(ch);
at_beginning = ch == '\n';
}

which gets changed to

while ((ch = getchar()) != EOF) {
if (at_beginning)
printf("%d ", ++line);
putchar(ch);
checksum += ch;
if (at_beginning = ch == '\n') {
printf("Checksum: %d\n", checksum);
checksum = -1;
}
}

(or, for those who see this as an even worse abomination than the simple
assignment, test 'at_beginning' after it).

This adds an 'if' whereas your change added only two statements, but
that is not a good measure of maintainability. Making the first program
more complex (in terms of it's logic) so that some changes might need
fewer lines later on does not strike me as the right route to
maintainability.
 
C

Chris H

Marcin Grzegorczyk said:
Obviously your opinion about the average programming skills of embedded
systems C programmers is higher than mine ;->

Having had to do many years of support work I find that those who think
they are clever and better than the average usually write "clever" but
un-maintainable code. Also the errors are far harder to find...... and
there will be error. Trouble is they tend to be less obvious in their
manifestation so wasting a lot of time to find them. I have seen many
real cases of this.

Also many programmers confuse compact source code with compact binary.
This is not always the case. In fact not usually the case.

Many compilers will produce the same binary for both examples above. All
you have saved is readability and increased the possibility less
obvious errors. I must dig out a similar example tot he one above
where the longer version actually produced smaller faster code than the
shorter source version.

Further more the first code example can easily be debugged in a C
debugger. Line by line. The second example can not as it is a single
line. Though you could drop in to assembler to see what it does. But
that takes time.

A lot of the "space saving " and "time saving " tricks people use in C
usually do neither.

Most C compilers are very efficient and tested to hell and back unlike
most embedded code. So keep it simple and readable so it is easier to
read and maintain.

After you have run the static analyser on the code let the compiler do
the clever stuff as it is a LOT less likely to make a mistake than you
will.
 
C

Chris H

Sherm Pendley said:
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it." --Brian Kernighan

sherm--


Interesting quote I have been saying much the same for years.
 
K

Keith Thompson

Chris H said:
Having had to do many years of support work I find that those who think
they are clever and better than the average usually write "clever" but
un-maintainable code. Also the errors are far harder to find...... and
there will be error. Trouble is they tend to be less obvious in their
manifestation so wasting a lot of time to find them. I have seen many
real cases of this.

Also many programmers confuse compact source code with compact binary.
This is not always the case. In fact not usually the case.

Many compilers will produce the same binary for both examples above. All
you have saved is readability and increased the possibility less
obvious errors. I must dig out a similar example tot he one above
where the longer version actually produced smaller faster code than the
shorter source version.

Further more the first code example can easily be debugged in a C
debugger. Line by line. The second example can not as it is a single
line. Though you could drop in to assembler to see what it does. But
that takes time.

A lot of the "space saving " and "time saving " tricks people use in C
usually do neither.

Most C compilers are very efficient and tested to hell and back unlike
most embedded code. So keep it simple and readable so it is easier to
read and maintain.

After you have run the static analyser on the code let the compiler do
the clever stuff as it is a LOT less likely to make a mistake than you
will.

I've confused this discussion before by ignoring some of the context, so
I'll leave it all in place this time.

So Chris, you're saying that you find
if (foo == bar) {
flag = 1;
}
else {
flag = 0;
}
more readable than
flag = (foo == bar);
and you consider the latter '"clever" but un-maintainable'?

I think we'll probably just have to agree to disagree on that.
I find the shorter form much more readable than the longer one.
Also the longer form is more vulnerable to typos, since you're
repeating much of the same information; I can see myself
copy-and-pasting the assignment and then changing the RHS on
the wrong one. Boolean values are values, and I have no problem
computing or manipulating them directly.

Upthread, you also (I think) said you prefer
if (flag == 1)
to
if (flag)
Can you expand on that? In particular, can you respond to my point
that flag might have a value other 0 or 1? Again, in my opinion
the longer form is both overly verbose with no increase in clarity,
and more error-prone.

And my preference has nothing to do with the amount of code I
expect the compiler to generate; I just find, in these cases,
that the shorter form expresses the intent more clearly.

And I'm probably a lot less enamored of terseness than a lot of
C programmers. I'm usually not very comfortable with the use of
"++" in conditions, for example, but like anyone who reads C code
I have to be prepared to understand it in code written by others.
 
B

Ben Bacarisse

Chris H said:
Interesting quote I have been saying much the same for years.

We seem to have moved off into the area of programming epithets rather
than specifics and helpful explanations, but if you'd like to bring it
down to earth, can I add my voice to Keith's requests for you to explain
why assigning the 0/1 integer valued result of == to an integer variable
"appalling and dangerous"?
 
E

Eric Sosman

Having had to do many years of support work I find that those who think
they are clever and better than the average usually write "clever" but
un-maintainable code. Also the errors are far harder to find...... and
there will be error. Trouble is they tend to be less obvious in their
manifestation so wasting a lot of time to find them. I have seen many
real cases of this.

Also many programmers confuse compact source code with compact binary.
This is not always the case. In fact not usually the case.

Many compilers will produce the same binary for both examples above. All
you have saved is readability and increased the possibility less
obvious errors. I must dig out a similar example tot he one above
where the longer version actually produced smaller faster code than the
shorter source version.

Further more the first code example can easily be debugged in a C
debugger. Line by line. The second example can not as it is a single
line. Though you could drop in to assembler to see what it does. But
that takes time.

A lot of the "space saving " and "time saving " tricks people use in C
usually do neither.

Most C compilers are very efficient and tested to hell and back unlike
most embedded code. So keep it simple and readable so it is easier to
read and maintain.

After you have run the static analyser on the code let the compiler do
the clever stuff as it is a LOT less likely to make a mistake than you
will.

Tastes certainly vary, but I find no savor in your arguments.
Let us take them one by one:

Longevity -- I've only written C since 1978, so perhaps you've
got more experience. Nolo contendere, point to you.

Cleverness -- I see absolutely nothing "clever" about computing
an `int' value and assigning it to an `int' variable. If that's the
sort of "cleverness" that baffles your programming staff, you have
problems that will not be solved by stylistic fiat.

Different kinds of compactness -- A non-issue, as the argument
cuts both ways with equal force: Just as there is no reason to think
that terse source produces more compact object, there is equally no
reason to think that bloated source produces more compact object.
Besides, "object compactness" is rather pointless to begin with,
except in circumstances when you ought to be writing assembly instead.
(Yes, I've written that kind of code; C is the wrong tool.)

Many compilers produce identical code -- You've made a statistical
study of this, and are prepared to quote percentages? Besides: If two
compilers do in fact produce the same code for one source line as for
six, why make the maintenance programmer read six lines instead of one?

Debugging -- The one-line form is *easier*, not harder, to deal
with in a line-at-a-time debugger. "Here I am at my breakpoint, step
one line, inspect the assigned value, fine, moving onward ..." Where's
the debugging difficulty?

Space-saving tricks -- Agreed, but what's your point? How does
"compute an `int' and assign to an `int' variable" qualify as a "trick?"

Keep it readable -- Absolutely! I've said before and will again
that there are two audiences for source code, compilers and programmers,
and that the latter are by far the more important. So why do you want
to make the programmers read nineteen tokens in six lines instead of
eight tokens on one? Bloat does not improve readability, as it fails
to say on the letterhead of the Department of Redundancy Dept.

Let the compiler do it -- By all means! Don't write six lines
instead of one because you think it'll help the compiler, just as
you wouldn't write six instead of one to "help" the reader.

In summary, I'll stick with my original "Balderdash!"
 
H

Hans Vlems

In message <[email protected]>, Marcin Grzegorczyk







Having had to do many years of support work I find that those who think
they are clever and better than the average usually write "clever" but
un-maintainable  code. Also the errors are far harder to find...... and
there will be error. Trouble is they tend to be less obvious in their
manifestation so wasting a lot of time to find them. I have seen  many
real cases of this.

Also many programmers confuse compact source code with compact binary.
This is not always the case. In fact not usually the case.

Many compilers will produce the same binary for both examples above. All
you have saved is readability and increased the possibility  less
obvious  errors.  I must dig out a similar example tot he one above
where the longer version actually produced smaller faster code than the
shorter source version.

Further more the first code example can easily be debugged in a C
debugger. Line by line. The second example can not as it is a single
line.  Though you could drop in to assembler to see what it does. But
that takes time.

A lot of the "space saving " and "time saving " tricks people use in C
usually do neither.

Most C compilers are very efficient and tested to hell and back unlike
most embedded code. So keep it simple and readable so it is easier to
read and maintain.

After you have run the static analyser on the code  let the compiler do
the clever stuff as it is a LOT less likely to make a mistake than you
will.

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills  Staffs  England     /\/\/\/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/- Tekst uit oorspronkelijk bericht niet weergeven -

- Tekst uit oorspronkelijk bericht weergeven -

In some ways C attracts the same kind of programmers as APL used to
do. Both languages may be used to construct programs that are unfit
for human inspection. Very likely this satisfies the ego ("I'm very
clever"). I agree with you Chris that generally complex statements are
difficult, if not impossible to maintain.
Coding the instruction i:=i+1 in C offers several possibilities: i=i
+1, i+=1 and i++.
Very likely the compiler in each case will emit the same code. There
is no advantage in terms of performance, just readability.
Now if you were writing software for an X application, with very long
variable names, then the += operator is a godsend.
A compact, difficult to read (and thus difficult to analyse) line of
code that does exactly the same as a more elaborate piece of code will
probably produce the same compiler output. So human readability is
more important than syntactical complexity unless there is just no
other way of doing it. And even then I'm inclined to think that
spending more time on thinking of a better solution is time well
spent.
Hans
 
C

Chris H

In message <[email protected].
com> said:
In some ways C attracts the same kind of programmers as APL used to
do. Both languages may be used to construct programs that are unfit
for human inspection. Very likely this satisfies the ego ("I'm very
clever"). I agree with you Chris that generally complex statements are
difficult, if not impossible to maintain.

That is the point. Trying to be clever usually defeats the object.
Coding the instruction i:=i+1 in C offers several possibilities: i=i
+1, i+=1 and i++.
Very likely the compiler in each case will emit the same code. There
is no advantage in terms of performance, just readability.

Quite so. In many cases the "long" version of the source will compiler
to as small (or smaller ) binary. The difference is that one is easier
to read (and therefore spot errors) by the average programmer. They are
also usually easier to debug at a source level with an ICE
Now if you were writing software for an X application, with very long
variable names, then the += operator is a godsend.

Agreed. But that is a single operator.
A compact, difficult to read (and thus difficult to analyse) line of
code that does exactly the same as a more elaborate piece of code will
probably produce the same compiler output. So human readability is
more important than syntactical complexity unless there is just no
other way of doing it. And even then I'm inclined to think that
spending more time on thinking of a better solution is time well
spent.

That is the point exactly. I have seen many times "clever" programmers
doing compact lines of source code that are not easily readable or easy
to debug. Try single stepping a complex multi part single line of
code.... It goes as one step. A bit like black box testing.

Several times when reconstructing a single line of complex and "clever"
code so it was readable and could be put over several lines of source
for ease of debugging we have found the error that was rather opaque.

The problem with these less readable lines They are far more prone to
errors that are less easy to spot or debug. As mentioned they rarely
take up less space in the binary and are very rarely more efficient.

A good compiler will have been tested to hell and back. Far more than
most embedded code will be. To let the compiler do the clever
compression and optimisation of the code. (After static analysis.)

Having spoken face to face with some of the "Greats" in C & C++ I find
they prefer a simple style and less complex lines that are easy to
debug. In fact it was Denise Ritchie who said they developed Lint in mid
70's because people were using legal but dubious constructs in C....

Here we are some 30 years later with people still trying to be too
clever. Even when they don't understand the basics that the space source
code takes up on the page is not related to the size of the binary
produced.
 
K

Keith Thompson

Chris H said:
In message <[email protected].


That is the point. Trying to be clever usually defeats the object.


Quite so. In many cases the "long" version of the source will compiler
to as small (or smaller ) binary. The difference is that one is easier
to read (and therefore spot errors) by the average programmer. They are
also usually easier to debug at a source level with an ICE


Agreed. But that is a single operator.


That is the point exactly. I have seen many times "clever" programmers
doing compact lines of source code that are not easily readable or easy
to debug. Try single stepping a complex multi part single line of
code.... It goes as one step. A bit like black box testing.

Several times when reconstructing a single line of complex and "clever"
code so it was readable and could be put over several lines of source
for ease of debugging we have found the error that was rather opaque.

The problem with these less readable lines They are far more prone to
errors that are less easy to spot or debug. As mentioned they rarely
take up less space in the binary and are very rarely more efficient.

A good compiler will have been tested to hell and back. Far more than
most embedded code will be. To let the compiler do the clever
compression and optimisation of the code. (After static analysis.)

Having spoken face to face with some of the "Greats" in C & C++ I find
they prefer a simple style and less complex lines that are easy to
debug. In fact it was Denise Ritchie who said they developed Lint in mid
70's because people were using legal but dubious constructs in C....

Here we are some 30 years later with people still trying to be too
clever. Even when they don't understand the basics that the space source
code takes up on the page is not related to the size of the binary
produced.

I agree with the general points you're making here -- but you're only
making very general points.

Where I strongly disagree is your apparent assertion that

if (foo == bar) {
flag = 1;
}
else {
flag = 0;
}

is clearer than

flag = (foo == bar);

or that

if (flag == 1) ...

is clearer than

if (flag) ...

In both of these *specific* cases, I find the shorter form clearer
-- not because I like terseness for its own sake (I don't), but
simply because the shorter form more clearly expresses (to me, and I
think to most C programmers) the intent. (And in the second case,
the two forms have different semantics, and the semantics of the
shorter form are more likely to be correct.)

Would you care to address these specific examples?
 
H

Hans Vlems

I agree with the general points you're making here -- but you're only
making very general points.

Where I strongly disagree is your apparent assertion that

    if (foo == bar) {
        flag = 1;
    }
    else {
        flag = 0;
    }

is clearer than

    flag = (foo == bar);

or that

    if (flag == 1) ...

is clearer than

    if (flag) ...

In both of these *specific* cases, I find the shorter form clearer
-- not because I like terseness for its own sake (I don't), but
simply because the shorter form more clearly expresses (to me, and I
think to most C programmers) the intent.  (And in the second case,
the two forms have different semantics, and the semantics of the
shorter form are more likely to be correct.)

Would you care to address these specific examples?

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"- Tekst uit oorspronkelijk bericht niet weergeven -

- Tekst uit oorspronkelijk bericht weergeven -

I can only speak for myself here. Both examples will do exactly the
same.
My first programming language was Algol, which has booleans so IF
<boolean> THEN ...
is more elegant than IF (<boolean==TRUE) THEN ....
OTOH in a language that uses integers for this purpose the argument
that a boolean expression is basically comparing
an integer expression value with zero and that this may just as well
be shown clearly in the source.
The point is of course that we all know that any non-zero integer
evaluattes as TRUE. But I understand the reasoning
behind it. However the penalty for doing so is well demonstrated in
the example that started this thread, i.e. using =
instead of ==.
Anyway, either method is surely better than a line of code that is so
syntactically complicated that a human would need
a lot of time figuring out what it does. APL programmers were very
good at that. Early assembler programmers too but at least
they had the excuse of very little memory and very slow hardware.
Hans
 
L

lawrence.jones

Chris H said:
In fact it was Denise Ritchie who said they developed Lint in mid
70's because people were using legal but dubious constructs in C....

That would be DMR's sister? :)
 
I

Ian Collins

That is the point exactly. I have seen many times "clever" programmers
doing compact lines of source code that are not easily readable or easy
to debug. Try single stepping a complex multi part single line of
code.... It goes as one step. A bit like black box testing.

Several times when reconstructing a single line of complex and "clever"
code so it was readable and could be put over several lines of source
for ease of debugging we have found the error that was rather opaque.

The problem with these less readable lines They are far more prone to
errors that are less easy to spot or debug. As mentioned they rarely
take up less space in the binary and are very rarely more efficient.

That is all too true!

I've often wondered why programmers who should know better write
conditional statements containing multiple, often complex, expressions.
There was an excuse with old inefficient compilers, but not any more.
One of the benefits of modern C is the ability to introduce variables
were they are needed, so the terms of a complex expression can be
assigned to temporary variables to be used in the conditional expression.

Or the whole thing can be extracted out into an inline function.
 
E

Eric Sosman

[...]
or that

if (flag == 1) ...

is clearer than

if (flag) ...
[...]
I can only speak for myself here. Both examples will do exactly the
same.

Have you considered the case where `flag' is 42?
My first programming language was Algol, which has booleans so IF
<boolean> THEN ...
is more elegant than IF (<boolean==TRUE) THEN ....
OTOH in a language that uses integers for this purpose the argument
that a boolean expression is basically comparing
an integer expression value with zero and that this may just as well
be shown clearly in the source.

Where do you stop?

if (((((flag == 1) == 1) == 1) == 1) == (1 != 0)) ...

Also, it's not just `int' values: Any scalar value can be tested
in a Boolean context. Personally, I prefer an explicit comparison
when the variable or function isn't "obviously" a Boolean to begin
with, and I have a special loathing for `if (strcmp(str1, str2))'.
Still, I find it a longish leap from "Some tests read awkwardly"
to "All tests must use operators."
The point is of course that we all know that any non-zero integer
evaluattes as TRUE. But I understand the reasoning
behind it. However the penalty for doing so is well demonstrated in
the example that started this thread, i.e. using =
instead of ==.

This seems to me a non sequitur. What has a confusion between
`=' and `==' got to do with whether an int can be tested "by itself"
and without a comparison operator? The issues seem orthogonal.
 
L

luser- -droog

I agree with the general points you're making here -- but you're only
making very general points.
Where I strongly disagree is your apparent assertion that
    if (foo == bar) {
        flag = 1;
    }
    else {
        flag = 0;
    }
is clearer than
    flag = (foo == bar);
[...]

I can only speak for myself here. Both examples will do exactly the
same. [...]
Anyway, either method is surely better than a line of code that is so
syntactically complicated that a human would need
a lot of time figuring out what it does. APL programmers were very
good at that. Early assembler programmers too but at least
they had the excuse of very little memory and very slow hardware.


True to my alleged nature as a Heathfield sock, I feel compelled to
side with Keith on this one. This very thread saved me from committing
a monstrosity. I preserved it for perverse delight in the comparison.

i = (i-1 >= 0)? i-1: d.u.c.n;
//--i; (void)(i<0? i=d.u.c.n: 0xF00);

Boolean assignment wins --hands down-- here.


El Hussar Del Droog
 
H

Hans Vlems

[...]
or that
     if (flag == 1) ...
is clearer than
     if (flag) ...
[...]
I can only speak for myself here. Both examples will do exactly the
same.

     Have you considered the case where `flag' is 42?
My first programming language was Algol, which has booleans so IF
<boolean>  THEN  ...
is more elegant than IF (<boolean==TRUE) THEN ....
OTOH in a language that uses integers for this purpose the argument
that a boolean expression is basically comparing
an integer expression value with zero and that this may just as well
be shown clearly in the source.

     Where do you stop?

        if (((((flag == 1) == 1) == 1) == 1) == (1 != 0)) ...

Also, it's not just `int' values: Any scalar value can be tested
in a Boolean context.  Personally, I prefer an explicit comparison
when the variable or function isn't "obviously" a Boolean to begin
with, and I have a special loathing for `if (strcmp(str1, str2))'.
Still, I find it a longish leap from "Some tests read awkwardly"
to "All tests must use operators."
The point is of course that we all know that any non-zero integer
evaluattes as TRUE. But I understand the reasoning
behind it. However the penalty for doing so is well demonstrated in
the example that started this thread, i.e. using =
instead of ==.

     This seems to me a non sequitur.  What has a confusion between
`=' and `==' got to do with whether an int can be tested "by itself"
and without a comparison operator?  The issues seem orthogonal.

Please re-read the post.
Hans
 
H

Hans Vlems

I agree with the general points you're making here -- but you're only
making very general points.
Where I strongly disagree is your apparent assertion that
    if (foo == bar) {
        flag = 1;
    }
    else {
        flag = 0;
    }
is clearer than
    flag = (foo == bar);
[...]

I can only speak for myself here. Both examples will do exactly the
same. [...]
Anyway, either method is surely better than a line of code that is so
syntactically complicated that a human would need
a lot of time figuring out what it does. APL programmers were very
good at that. Early assembler programmers too but at least
they had the excuse of very little memory and very slow hardware.

True to my alleged nature as a Heathfield sock, I feel compelled to
side with Keith on this one. This very thread saved me from committing
a monstrosity. I preserved it for perverse delight in the comparison.

        i = (i-1 >= 0)? i-1: d.u.c.n;
        //--i; (void)(i<0? i=d.u.c.n: 0xF00);

Boolean assignment wins --hands down-- here.

El Hussar Del Droog- Tekst uit oorspronkelijk bericht niet weergeven -

- Tekst uit oorspronkelijk bericht weergeven -

Well, if only C had built-in support for booleans ;-)
 
K

Keith Thompson

Hans Vlems said:
Well, if only C had built-in support for booleans ;-)

Were you unaware that it does?

But even in pure C90, which doesn't have _Bool/bool, the lack of
*direct* support for a boolean type is largely irrelevant. Several
built-in operators ("==", "<", "!", etc.) yield int results that are
either 0 or 1, representing false or true results. For example:

int flag;
...
flag = (foo == bar);
...
if (flag) {
...
}

flag is an int, but there is absolutely nothing wrong with treating it
as an object holding a logically boolean value.

I think you're saying that the fact that it's an int implies that the
above should be written as:

int flag;
...
if (foo == bar) {
flag = 1;
}
else {
flag = 0;
}
...
if (flag == 1) { /* or, better, if (flag != 0) */
...
}

I find this second form far too verbose and substantially less clear.

In effect, C90 *does* have a boolean type; it's called "int".

We can use ints for a variety of things: counts, array indices,
arbitrary unique values, or boolean conditions. The lack of distinct
types for these different purposes does introduce some risk of
incorrectly mixing logically incompatible uses, but the answer to
that is to code carefully, not to add *unhelpful* verbosity.
 
M

Marcin Grzegorczyk

Chris said:
Having had to do many years of support work I find that those who think
they are clever and better than the average usually write "clever" but
un-maintainable code. Also the errors are far harder to find...... and
there will be error.

Too true.
However, one has to balance simplicity and verbosity. At some point
verbosity becomes visual cruft, and actually hampers understanding of
the code.
Also, as posts in this thread have shown, what is clever but obscure to
one programmer may be idiomatic and immediately clear to another; and
what is clear and simple to one programmer may be annoyingly verbose to
another.

In the end it boils down, I think, to what kind of C idioms people who
will have to debug your code do you expect to be familiar with. If
they're not familiar with things like assigning the result of an
equality operator, you might better avoid that. (This applies to the
programmers themselves, of course: if you consider Keith's second
example quoted above clever and un-idiomatic, you're doing yourself a
service not doing that. Sherm Pendley's quote from Kernighan is
relevant here.)
Also many programmers confuse compact source code with compact binary.

Oh, I'm not talking about *that* level of incompetence ;-)

[snip]
Further more the first code example can easily be debugged in a C
debugger. Line by line. The second example can not as it is a single
line.

I disagree here. Whether the result of an equality operator is stored
in a variable, or results in either of two lines being executed, it is
equally debuggable.

Now, if the result of the equality operator were assigned to something
other than an ordinary variable, especially an expression that involved
the conditional operator or a function call, I'd probably agree. Same
if `foo` and `bar` were, in fact, complex expressions involving function
calls. It's all about being able to see what's going on without
resorting to assembly-level debugging.
A lot of the "space saving " and "time saving " tricks people use in C
usually do neither.

Sure. But Keith's example was not about reducing either code size or
execution speed. Unless you mean *screen* space saving; then Keith's
second example clearly does that.
 
H

Hans Vlems

Were you unaware that it does?

But even in pure C90, which doesn't have _Bool/bool, the lack of
*direct* support for a boolean type is largely irrelevant.  Several
built-in operators ("==", "<", "!", etc.) yield int results that are
either 0 or 1, representing false or true results.  For example:

    int flag;
    ...
    flag = (foo == bar);
    ...
    if (flag) {
        ...
    }

flag is an int, but there is absolutely nothing wrong with treating it
as an object holding a logically boolean value.

I think you're saying that the fact that it's an int implies that the
above should be written as:

    int flag;
    ...
    if (foo == bar) {
        flag = 1;
    }
    else {
        flag = 0;
    }
    ...
    if (flag == 1) { /* or, better, if (flag != 0) */
        ...
    }

I find this second form far too verbose and substantially less clear.

In effect, C90 *does* have a boolean type; it's called "int".

We can use ints for a variety of things: counts, array indices,
arbitrary unique values, or boolean conditions.  The lack of distinct
types for these different purposes does introduce some risk of
incorrectly mixing logically incompatible uses, but the answer to
that is to code carefully, not to add *unhelpful* verbosity.

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

<g>
I'm aware of C90's boole type and the way an int is easily used as a
substitute.
Hans
 

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,091
Messages
2,570,605
Members
47,225
Latest member
DarrinWhit

Latest Threads

Top