Beginner post-increment question

S

Stang1

The following statement:

line_buf[line_len++] = ' ';


is equivalent to:

line_buf[line_len] = ' ';
line_len++;

because post-increments are done AFTER the non-incremented values are
used in the statement.


Correct?
 
D

DiAvOl

yes, it's correct but note that you should avoid to:

1) use the increment or decrement operators on a variable that appears
more than once in an expression

For example avoid using constructs like the following

n = 1;
y = n++ + n++;

2) use the increment or decrement operators on a variable that is part
of more than one argument of a function

Example to avoid

printf("%d %d\n", number, number*number++);

The reason is because the second argument might be evaluated before
the first one
 
R

Richard Heathfield

Stang1 said:
The following statement:

line_buf[line_len++] = ' ';


is equivalent to:

line_buf[line_len] = ' ';
line_len++;

because post-increments are done AFTER the non-incremented values are
used in the statement.


Correct?

Nearly. In fact, it's correct enough for rock n' roll.

What follows probably seems a bit picky at present, but can matter when the
expressions get more complicated.

The order of evaluation is up to the implementation, provided that, at
certain points in the program (known as "sequence points"), everything
that should have been done by that point /has/ been done by that point.

So, for example, a compiler could legally translate:

line_buf[line_len++] = ' ';

by copying the value of line_len to *two* registers, say R1 and R2,
incrementing R1, storing R1 back into line_len, and then setting
line_buf[R2] equal to ' '.

Why would a compiler do this? Well, it may determine that it's the most
efficient way to do the operation on a particular architecture. Perhaps
the hardware can do the inc/store and the array update in parallel, or
something.

Your code is well-defined as written. The proper element of line_buf will
be updated, regardless of which of many correct translations is chosen.
But if the order in which subexpressions are evaluated matters to you,
break it down into several statements, with one evaluation per statement.
For example, if foo() and bar() each produced output as well as returning
a value, then if the order in which the outputs were produced is important
you should write: n = foo(); n += bar(); arr[n] = 6; rather than arr[foo()
+ bar()] = 6; because, in the latter, code, the compiler is free to call
foo() and bar() in either order.
 
B

borkhuis

DiAvOl said:
yes, it's correct but note that you should avoid to:

1) use the increment or decrement operators on a variable that appears
more than once in an expression

For example avoid using constructs like the following

n = 1;
y = n++ + n++;

2) use the increment or decrement operators on a variable that is part
of more than one argument of a function

Example to avoid

printf("%d %d\n", number, number*number++);

The reason is because the second argument might be evaluated before
the first one

You forgot the one thing to avoid:

3) Never use pre or post increment as parameters to macros, as a macro
might use the parameter more than once. As a consequence, item 2
should be "never use increment or decrement on parameters to a
function", as you might not know if this is a real function, or that
this was implemented as a macro.

Kind regards,
Johan Borkhuis
 
K

Keith Thompson

3) Never use pre or post increment as parameters to macros, as a macro
might use the parameter more than once. As a consequence, item 2
should be "never use increment or decrement on parameters to a
function", as you might not know if this is a real function, or that
this was implemented as a macro.

The standard library functions may be additionally implemented as
macros, but any such macros must evaluate each of their arguments
exactly once (except for a very few cases that are explicitly
documented).

As for functions outside the standard library, they could well follow
the same convention, in which case passing expressions with side
effects as arguments is no more of a problem than it would be for
standard library functions.

Macros names are conventionally in all-caps; this is at least partly
to remind the programmer to be cautious about side effects in
arguments.

If a library provides a function-like macro that evaluates its
arguments more than once, then it had better document this fact. If
it pretends that the macro is equivalent to a corresponding function
when it really isn't, then that's a serious flaw in the library.
 
P

pete

Stang1 said:
The following statement:

line_buf[line_len++] = ' ';

is equivalent to:

line_buf[line_len] = ' ';
line_len++;

because post-increments are done AFTER the non-incremented values are
used in the statement.

Correct?

The equivalence is true.
Your reason is completely wrong.

These two expressions are also interchangebly equal:

(line_buf[line_len++] = ' ')

(line_buf[++line_len - 1] = ' ')

Your original c code statement,
had only one sequence point,
and two assignment operations.

The assignment operation on line_len,
could happen either before or after
the assignement to line buff[line_len].

Operations and side effects between sequence points,
can occur in any order.

(line_len++) has a value and a side effect.
The side effect of the expression,
is that line_len gets incremented.
The value of the expression,
is the value that the expression had prior to the increment operation.
But there is no order between the assignment operation
and the evaluation of the expression in (line_len++).
 
P

pete

Keith said:
The standard library functions may be additionally implemented as
macros, but any such macros must evaluate each of their arguments
exactly once (except for a very few cases that are explicitly
documented).

The exact number of cases, is two: getc and putc.

The standard also explicitly states
that the stream arguments with side effects,
should not be used with getc and putc.
 
F

Flash Gordon

DiAvOl wrote, On 15/01/08 01:16:

Please quote enough of the post you are replying to for your post to
make sense on it's own. There is no guarantee that everyone will *ever*
see the post your replying to.
yes, it's correct but note that you should avoid to:

2) use the increment or decrement operators on a variable that is part
of more than one argument of a function

Example to avoid

printf("%d %d\n", number, number*number++);

The reason is because the second argument might be evaluated before
the first one

It's worse than that it's dead Jim...

The expression
number * number++;
is Undefined Behaviour (i.e. *anything* can happen) because number is
modified (by number++) and also evaluated to do something other than
generate that new value.

The statement
printf("%d %d\n", number, number++);
invokes undefined behaviour not because the arguments can be evaluated
in any order (which they can) but because number++ is again modified and
evalutated for something other than generating the new value between
sequence points (the comma is a separator here and not a comma operator).

The statement
printf("%d %d", foo(), bar());
does *not* invoke undefined behaviour. foo and bar could be called in
either order, but this is only *Unspecified* behaviour so unlike with
the previous examples the implementation is *not* free to feed your
mother to the ravenous bug blatter beast of traal.
 
C

CBFalconer

Keith said:
.... snip ...

The standard library functions may be additionally implemented as
macros, but any such macros must evaluate each of their arguments
exactly once (except for a very few cases that are explicitly
documented).

I believe the only ones that meet that specification are putc and
getc. All others are covered by the 'one evaluation' phrase.
 
C

CBFalconer

Flash said:
.... snip ...

implementation is *not* free to feed your mother to the
ravenous bug blatter beast of traal.

Ahh. That explains many of my problems. :)
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top