Question About Strange 'C' Code Syntax ( Well strange to me anyway )

Discussion in 'Embedded' started by Harvey Twyman, Oct 23, 2003.

1. Dave HansenGuest

Um, no. Fron n869 6.8.4.1 (The if statement) paragraph 2 (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.

There is no typecasting. Until C99, there is no boolean type. Even
in C99, values of type _Bool are promoted (to int in most cases)
before any operators can be applied. E.g., given

_Bool b;

if (b != 0)

The value of b is first promoted to int (by the usual arithmetic
conversions) before being compared to (the int constant) 0. Even with

if (b != (_Bool)0)

The zero is cast to _Bool, which is then promoted to int. In all
cases, the result of the != operator has type int.

Regards,

-=Dave

Dave Hansen, Oct 27, 2003

2. Morris DoveyGuest

It's the same in ISO/IEC 9899:1999(E). Thanks!

Morris Dovey, Oct 28, 2003

The issue isn't the # of lines, but the readability and flow. It's *EASY* to
miss a question mark. It 'aint easy to miss the above even though it's more
verbose.
As one who integrates code from 4 different groups around the world (a total
of 30 engineers), I'll show you quite a few who would completely blow that
statement.
Never said it was hard to comprehend. I said it was easy to miss. Burying a
question mark in the middle of an expression is just a bad idea.

-->Neil

From the current C standard ANSI/ISO/IEC 9899-1999:

6.3.1.2 Boolean type § 1

When any scalar value is converted to _Bool, the result
is 0 if the value compares equal to 0; otherwise, the
result is 1.

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).

6.5.8 Relational operators § 6

Each of the operators < (less than), > (greater than),
<= (less than or equal to), and >= (greater than or
equal to) shall yield 1 if the specified relation is
true and 0 if it is false.89) The result has type int.

6.5.9 Equality operators § 3

The == (equal to) and != (not equal to) operators are
analogous to the relational operators except for their
lower precedence.90) Each of the operators yields 1 if
the specified relation is true and 0 if it is false.
The result has type int. For any pair of operands,
exactly one of the relations is true.

6.5.13 Logical AND operator § 3

The && operator shall yield 1 if both of its operands
compare unequal to 0; otherwise, it yields 0. The result
has type int.

6.5.14 Logical OR operator § 3

The || operator shall yield 1 if either of its operands
compare unequal to 0; otherwise, it yields 0. The result
has type int.

The boolean type _Bool was added in the 1999 revision, but the
rest has been the same since Kernighan and Ritchie published the
first edition of "The C Programming Language", i.e. long before
the first C standard.

5. Spehro PefhanyGuest

It's clear that one of the values should be 0 because testing for zero
is virtually always a fast operation in machine code. Whether you
choose 0 for TRUE or FALSE is a matter of taste.

A language that emphasized other things than speed and simplicity
might choose to interpret anything other than 0 or (say) 1 as an
invalid state and deal with it as such, but that is not in the C
philosophy.

With C you *can* write legitimate warning-free stuff like:

c += a = ++a == b++;

It might even make sense (at the time).

Best regards,
Spehro Pefhany

Spehro Pefhany, Oct 28, 2003

You can write lots of legitimate code that looks strange, but this
one is not legitimate, it invokes undefined behaviour. The example
statement updates the variable ``a'' twice without an intervening
sequence point.

From ANSI/ISO/IEC 9899-1999:

6.5 Expressions § 2

2 Between the previous and next sequence point an object
shall have its stored value modified at most once by
the evaluation of an expression. Furthermore, the prior
value shall be read only to determine the value to be
stored.70)

70) This paragraph renders undefined statement
expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a = i;
No. Even the C compiler isn't required to make sense of it.

7. GuestGuest

:
: With C you *can* write legitimate warning-free stuff like:
:
: c += a = ++a == b++;
:

You can, but the results of that statement may not be the same on all
compilers...too many side-effects.

Okay, it _might_ be the same on all compilers, but it might not

Nice code though!

(On a side note, i really want to kick my self when i use macros with
++...ie FOO(c++) or FOO(++c), especially if FOO uses it's argument more
than once...

even worse is FOO(a+b,c) which could do anything, if FOO() isn't written
properly (ala #define FOO(ab,c) ((ab) * (c) + (ab))

Without the extra ( ), that macro won't work at all with an arg of a+b.
The preprocessor can really bite you when it wants to

Regards,

--buddy

Guest, Oct 28, 2003
8. Dave HansenGuest

On Tue, 28 Oct 2003 13:21:51 GMT, Spehro Pefhany

[...]
Well, you can write it, and it need not generate a diagnostic, but
it's not legitimate. It invokes undefined behavior. The variable a
is modified twice between sequence points.

However,

c += d = ++a == b++;

would work to illustrate your point. And as you say, might even make
sense at the time, though it wouldn't get through my code review
without at least one, and most likely two sets of parentheses...

Regards,

-=Dave

Dave Hansen, Oct 28, 2003
9. Spehro PefhanyGuest

<snip>

Good point. One would need to add a "," in there to make it valid C.
I was under the (mistaken) impression that "==" was guaranteed to
provid a sequence point (as || and && do).

(It does happen to compile without warnings and do what you'd expect
with a few compilers I tried it on, FWTF*T*W- NM).

Best regards,
Spehro Pefhany

Spehro Pefhany, Oct 28, 2003

[/QUOTE]
That would not help. Placing a sequence point at ``=='' does
not insert a sequence point between the ``a ='' and ``++a''
in ``a = ++a''.

11. Grant EdwardsGuest

NO it isn't. Any non-zero value is true. 0xF0 is "true". Doing a 1's
compliment on that results in 0x0F: also true. Using 1's compliment to
impliment "!" is quite simply NOT C.

Grant Edwards, Oct 28, 2003
12. Spehro PefhanyGuest

That would not help. Placing a sequence point at ``=='' does
not insert a sequence point between the ``a ='' and ``++a''
in ``a = ++a''.[/QUOTE]

If we replace "==" with "||", it would put a sequence point at the end
of the first operand to "||".

Best regards,
Spehro Pefhany

Spehro Pefhany, Oct 28, 2003
13. Dave HansenGuest

On Tue, 28 Oct 2003 17:50:31 GMT, Spehro Pefhany

[...]
That only helps if a == -1 before the statement is executed (which
would result in ++a == 0 and force the execution of b++).

It also changes the meaning of the expression...

You could fix it with a comma operator and a temporary:

c += t = ++a == b++, a=t;

Or, since we're apparently intending to throw away the result of ++a
anyway,

c += a = a+1 == b++;

Regards,

-=Dave

Dave Hansen, Oct 28, 2003
14. Dennis ClarkGuest

Or we could just write readable code and leave the games at the door with
the "most obtuse C code" competition every year. Really guys, writing
obscure code does not make it run faster, in fact, often just the reverse.

I've seen for{} loops written where all the processing occurs in the ()
section and nothing in the {} brackets - Who the heck is that code for?
It sure isn't for the poor sot that has to support it!

and stop trying to play "stump the chump" with the compiler. With embedded
work, you'll often get better performance and smaller code size.

IMO,
DLC

: On Tue, 28 Oct 2003 15:56:13 GMT, the renowned

:>In article <>,
:>
:>> >> c += a = ++a == b++;
:>
:>> Good point. One would need to add a "," in there to make it valid C.
:>> I was under the (mistaken) impression that "==" was guaranteed to
:>> provid a sequence point (as || and && do).
:>
:>That would not help. Placing a sequence point at ``=='' does
:>not insert a sequence point between the ``a ='' and ``++a''
:>in ``a = ++a''.

: If we replace "==" with "||", it would put a sequence point at the end
: of the first operand to "||".

: Best regards,
: Spehro Pefhany
: --
: "it's the network..." "The Journey is the reward"
: Info for manufacturers: http://www.trexon.com

Dennis Clark, Oct 28, 2003
15. Chris HillsGuest

I though that was the document that everyone was quoting? What other
document is the C standard (except perhaps the 9899:1990 which many
compilers still use)

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\
/\/\/ www.phaedsys.org \/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Chris Hills, Oct 29, 2003

[/QUOTE]
The document known as n869 is a committee draft of the
ISO/IEC 9899:1999 standard document. The n869 draft was
created early in 1999 and was available for a while from
changes were made between the n869 draft and the final
standard.

Some people still quote from the obsolete n869, perhaps
they like to create confusion, or are too poor to spend, IIRC,
US\$14 to buy the real document.
The 9899:1990 is no longer current and has been retracted.
It consisted of:

ISO/IEC 9899:1990 (standard)
ISO/IEC 9899 AM1 (amendment, 1995)
ISO/IEC 9899 TCOR1 (technical corrigendum 1, 1995)
ISO/IEC 9899 TCOR2 (technical corrigendum 2, 1996)

The only documents describing the current C standard are:

ISO/IEC 9899:1999 (standard)
ISO/IEC 9899 Cor1 (corrigendum 1, 2001)

17. Chris HillsGuest

This is correct except that BSI has made
ISO/IEC 9899 TCOR2 (technical corrigendum 2, 1996)
available again simply because a lot of compilers still work to is and
are not moving to C99. Also there are quite a few standards that still
reference C90 specifically. As many of these are in the embedded, safety
critical and high integrity areas companies are required to have copies
of the base standards.

AFAIK there are currently only 2 compilers claiming C99 compliance
anyway.

However any one who starts quoting a committee draft is asking for
trouble!!

Regards
Chris
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\
/\/\/ www.phaedsys.org \/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Chris Hills, Oct 30, 2003

The reason for making the ISO/IEC 9899:1990 series available again
was that the current C++ standard refers to 9899:1990. That does not
make it a valid C standard, only an apendix to the C++ standard.
That is why it was made available again. It has still been superseeded
by the 9899:1999 standard.
True. There is a reason why it was removed from the website run by the
working group.

19. Chris HillsGuest

You are wrong on this.
Not at all. It is a valid C standard. It is just an obsolete standard.
Yes. It was nothing to do with the C++ standard.
We agree on that.

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\
/\/\/ www.phaedsys.org \/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Chris Hills, Oct 30, 2003