Re: Definition of expression and statement.
- From: somenath <somenathpal@xxxxxxxxx>
- Date: Tue, 1 Jan 2008 22:55:11 -0800 (PST)
On Dec 30 2007, 3:48 am, Chris Torek <nos...@xxxxxxxxx> wrote:
In article <2ba7f533-bdeb-4d0a-8348-34b8442a2...@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>
dspfun <dsp...@xxxxxxxxxxx> wrote:
The words "expression" and "statement" are often used in C99 and C-
textbooks, however, I am not sure of the clear defintion of these
words with respect to C.
Others have gone through a lot of examples and given various
corrections. I would just like to emphasize a few details.
Can somebody provide a sharp defintion of "expression" and
"statement"? What is the difference between an expression and a
statement?
As at least one person noted, the real heart of the difference is
actually syntactic. An "expression" is that which is permitted
syntactically by the grammar in the C Standard (whichever standard
you use -- C89 or C99).
In any case, *every* C expression can be turned into a statement
simply by adding a semicolon at the end, but the reverse is not
true. This is because the grammar (C89 or C99, either one) has
various additional things recognized as "statement" that, even if
they end with a semicolon, are not recognized as an "expression"
without that semicolon. For instance, a while loop:
while (expr) statement;
is itself a statement (specifically, an "iteration-statement"),
but removing the semicolon does not turn it into an expression.
The C99 grammar includes the following fragments:
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
expression-statement:
expression-opt ;
This last (the expression-statement part of the grammar) is why
any expression can be turned into a statement.
The fact that a while loop (like a do-while or for loop) is recognized
only by the "iteration-statement" part of the grammar is why it
does not become a statement when removing the semicolon.
Last, although this is not relevant to the distinction between
"expression" and "statement": There is a key item here that I
think many people miss here as well:
1++ //Type: int. Value: 2, right?
a++ //Type: Depends on a. Value: One more than a.
(As others noted, "1++" is a constraint violation and thus requires
a diagnostic. "a++" is OK -- that is, is not a constraint violation
as long as "a" is a "modifiable lvalue". It may have undefined
behavior, e.g., if a is an "int" variable and is initially set to
INT_MAX, but no diagnostic is required for this, and programmers
should not expect one. The value is not "one more than a", but
rather, "the value a had before the increment took place".)
In C, expressions produce values (with one possible exception:
expressions of type "void" produce no value, or produce "a value
of type void", depending on who you ask; even the C Standard appears
to be a bit confused on this issue :-) ). However, expressions
also have "side effects". (A "side effect" is, loosely speaking,
a change in a variable. Things like printing output are also
"side effects" in computing theory, although in C this is simply
done with function calls, e.g., printf(). Side effects are quite
important in computing theory because operations *without* side
effects are always completely reversible. This means that "debugging"
is, at its heart, simply the process of tracking all side effects
-- all other operations can be trivially backed-up-over.)
The various modifier operators, including the prefix and postfix
increment and decrement, have TWO uses: they (a) produce a value,
and (b) have a side effect. Sometimes, in programming in C, we
want a value; sometimes we want a side effect; sometimes we even
want both. We can use these modifier operators for their side
effects, or for both their values *and* their side effects. For
instance, in a loop like:
for (i = 0; i < N; i++)
we have two modifier-operators: initally we set i to 0, and each
time at the end of the loop, we increment i. Here, the "=" operator
is used purely for its side effect: it sets i to 0. The value of
the entire operation is 0, but this value is discarded. Similarly,
the "++" operator produces a value -- in this case, the previous
value of i -- but we throw that value away, as the only thing we
want is the side effect, of increasing i by 1.
Because we only want the side effect, we could use any other operation
that *also* increases i by 1:
for (i = 0; i < N; ++i)
and:
for (i = 0; i < N; i = i + 1)
are all equally valid ways to write the loop.
Examples of places where we want *both* the value *and* the side
effect are not quite as common, but do occur. For instance, if p
points into a string that contains some 'x' characters, and *p is
currently one of the 'x' characters, the following line skips over
that x and any subsequent 'x', so that *p will be whatever character
comes after the "x"s. E.g., if p points into "hexxllo world", *p
will be 'l' after the loop ends; if it points into "magix", *p will
be '\0':
while (*p++ == 'x')
continue;
Here, the "++" operator is used both for the value it produces --
i.e., "give me the value p had before an increment occurs" -- and
for its side effect -- i.e., "and also please increment p before
the next sequence point". (The old value of p is then given to
the unary "*" operator, which fetches the character to which p
pointed before the increment happened. The compiler is free to
arrange for p to be incremented first or last or anywhere in between,
as long as it manages to fetch *(whatever_p_used_to_be). On some
machines, it may make sense to increment p first, then fetch p[-1];
on some, it may make sense to increment p last; on some, it may be
possible to increment p while simultaneously fetching, e.g., using
the auto-increment addressing mode on a PDP-11, or the writeback
feature of the ARM.)
Something some C programmers do, but I claim is dodgy at best, is
use modifier operators purely for their value. For instance,
consider the following rather silly function, and an example of
its use:
int three_more(int x) {
return x += 3;
}
#include <stdio.h>
int main(void) {
printf("%d\n", three_more(39));
return 0;
}
which prints 42. The three_more() function uses the "+=" operator
to modify x (a side effect) *and* produce a value (the value x will
have after the increment-by-3), but -- by returning, in this case
returning the value-after-increment -- immediately throws away the
incremented variable "x". This is valid, "legal" C code, but to
me it "makes more sense" to write:
int better_three_more(int x) {
return x + 3;
}
For some reason, beginning C programmers often seem to be fascinated
by the "double effect" of modifier operators -- especially the
prefix and postfix increment and decrement operators -- that have
both a side effect *and* a value, and wind up "overusing" them (as
in three_more() above). This seems to lead to the desire to write
things like "1++" or "++41", which are not only pointless (a la
the modification to x in three_more()), but invalid (draw a
diagnostic, and usually fail to compile at all).
I would like to request you to explain why you are indicating second
function as better.
I would like to clarify my self why I requested so. I was reading one
C text book which is famous in our country it says as mentioned.
"These instructions increase directly specify the required information
so help in faster execution. 'C' makes
efficient use of this feature by providing compound statements for
which translation can be done directly to
its corresponding machine instruction. For example:
140
a=a+10;
may be converted to,
MOV AX,_a
ADD 10
MOV _a, AX
Whereas a+=10; may be converted directly to,
INC _a, 10
in some machine."
So according to this logic first function "int three_more(int x)"
may be faster then the "int better_three_more(int x)". Is it not
correct ?
.
- Follow-Ups:
- Re: Definition of expression and statement.
- From: James Kuyper
- Re: Definition of expression and statement.
- From: Chris Torek
- Re: Definition of expression and statement.
- From: Richard Heathfield
- Re: Definition of expression and statement.
- Prev by Date: Re: Secure C programming
- Next by Date: Re: confused..again
- Previous by thread: Compiling source code out of the blue
- Next by thread: Re: Definition of expression and statement.
- Index(es):
Relevant Pages
|