i++, ++i, i+=1 and i = i+1;

J

jim

Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

result (for value of i) of all 4 will be same; could anyone tell
differences among them from any perspectives?
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

Thanks in advance,
 
R

Richard Heathfield

jim said:
Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

result (for value of i) of all 4 will be same; could anyone tell
differences among them from any perspectives?
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

Use the one you think most clearly conveys your intent. Premature
optimisation is the root of all evil, as Donald Knuth rightly said.
 
R

Random832

2006-12-19 said:
jim said:


Use the one you think most clearly conveys your intent. Premature
optimisation is the root of all evil, as Donald Knuth rightly said.

Note that 1 does have a meaning slightly different than 2 3 or 4, if
used in an expression.

Any compiler worth anything will compile all four [in a statement by
themselves, and 2 3 4 anywhere in an expression] to exactly the same
thing - so, yeah, use whichever one is most readable. And "i+++1"
instead of "++i" is just silly.
 
S

Stephen Sprunk

jim said:
Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

result (for value of i) of all 4 will be same; could anyone tell
differences among them from any perspectives?
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

If those lines are the entirety of the relevant expressions, there is
absolutely no difference to modern compilers. One may express your
intent better than the others, which may help other folks understand
your code, but they'll end up the same when compiled.

It used to be true, back in the 70s and 80s, that some forms were faster
than others because compilers weren't very good at optimizing, and such
advice was actually helpful. Someone spouting the same advice today,
however, is merely propogating urban legends; beware of anything you get
from such a source.

S
 
P

Peter Nilsson

jim said:
Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

result (for value of i) of all 4 will be same;

Better to say the side effect will be the same, the result of the
expression is clearly
different for the first case.
could anyone tell differences among them from any perspectives?

As stand alone statements, there's none.
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

You most likely heard that in a C++ context with particular reference
to
i being an iterator. Note that C and C++ are different languages with
different paradigms and you'll only confuse yourself if you mix the
two. [From the question I'm assuming you're a relative newbie.]

So if you're currently learning C++, I suggest you hop over to a C++
group. Note that this question is almost certainly a FAQ though.

If you're currently learning C but have been reading C++ material
in the belief that it's similar, DON'T!
 
P

pete

Random832 said:
Note that 1 does have a meaning slightly different than 2 3 or 4, if
used in an expression.

4 can have a different meaning from the other three
if i is a macro with side effects.
 
D

David T. Ashley

jim said:
Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

Any modern compiler is going to recognize them all as an increment on an
integer, and the generated code will be the same.

However, if one tries to use the value of the expression ... that is a
different matter.

The four statements:

j = (i++);
j = (++i);
j = (i += 1);
j = (i = i+1);

will give two different results.

Most people will use "i++" for simple iteration, as in:

for (i=0; i<10; i++)
do_whatever();

or

while(pointer)
{
val = *pointer;
pointer++;
}
 
A

August Karlstrom

jim skrev:
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

result (for value of i) of all 4 will be same; could anyone tell
differences among them from any perspectives?
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

As Peter mentioned, you most likely heard that in a C++ context where
the increment operation is being overloaded. Try to implement the
following functions to get a feeling for the difference between 1 and 2:

/* Increment the integer pointed at and return the new value. */
int preinc(int *p);

/* Increment the integer pointed at and return the old value. */
int postinc(int *p);


August
 
W

websnarf

jim said:
Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;
result (for value of i) of all 4 will be same; could anyone tell
differences among them from any perspectives?

In isolation there is no difference between any of them.

On the other hand, if you use any of them as the component of an
expression, then the first one can be different.

int i, j;

i = 2;
j = i++; /* j will become 2, i will become 3 */

i = 2;
j = ++i; /* j will become 3, i will become 3 */

i = 2;
j = (i += 1); /* j will become 3, i will become 3 */

i = 2;
j = (i = i + 1); /* j will become 3, i will become 3 */

There are more implications for what all this means for C++ and its
operator overloading feature, however that's another suject entirely.
There are probably some implications depending on if i is declared
volatile and sig_atomic_t as well, but I'm too lazy to work them all
out.
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

Its not *better* to use any of them. There is a subtle difference in
them so you should use one that is appropriate to your purpose. C
abstracts them all to nearly the same thing at compile time, so there
is no reason for their to be any speed difference in any of them
(matters are slightly different for C++ operator overloading.)
 
R

Richard Heathfield

malc said:
http://en.wikipedia.org/wiki/Optimization_(computer_science)
Third paragraph. I think the credit must go where it's due.

Hmmm. What makes you think the Wikipedia article is correct? After all, if
you look up their C stuff, you'll find that they confuse arguments and
parameters at least twice, claim that * is a type qualifier, and assume
that all platforms use ASCII.

We all know that *anyone* can edit Wikipedia, regardless of their level of
knowledge of the subject matter, so why treat the Wiki like some kind of
oracle? It's only as good as the last person to edit it. If that was
someone who happens to know his or her stuff, you get good information. And
if it wasn't, you get bad information.

So the question a Wiki reader has to ask himself is: "do I feel lucky?"
 
G

Guest

jim said:
Hello,
let say we have;

1) i++; /* use i and increment by one */
2) ++i; /* increment i by one and use it */
3) i += 1;
4) i = i+1;

result (for value of i) of all 4 will be same; could anyone tell
differences among them from any perspectives?
I heard we'd better use 2) over 1). And 1) is faster than 3) or 4).

Thanks in advance,

I was told that in case 3) "i" is accessed once and modified once;
in case 4) "i" is accessed twice and modified once.

Someone else could hopefully say if it is true and what it means in reality.

/Krister
 
M

malc

Richard Heathfield said:
malc said:
[..snip..]
http://en.wikipedia.org/wiki/Optimization_(computer_science)
Third paragraph. I think the credit must go where it's due.

Hmmm. What makes you think the Wikipedia article is correct? After all, if
you look up their C stuff, you'll find that they confuse arguments and
parameters at least twice, claim that * is a type qualifier, and assume
that all platforms use ASCII.

Well, i knew that i have seen discussions on the subject in the past,
decided to check with wikipedia and there it was. Furthermore:

http://www.google.com/search?q=premature optimizations hoare

yields a lot of hits.

All that said, cursory look on the paper where this quote is taken
from (and out of context if i might add) does not suggest that Knuth
is quoting Hoare.

Structured Programming with go to Statements

DONALD E. KNUTH

Stanford University, Stanford, California 94305

page 268

<quote>
We should forget about small efficiencies, say about 97% of the time:
premature optimization is the root of all evil.
</quote>

The first part of the quote makes the rest of it a lot less of a
sweeping generalization.

After spending some time searching the web i have no definitive proof
that Knuth was quoting Hoare, so sorry about that.

Then again taking less than a half of a sentence and using that as an
appeal to authority is not a right thing to do.
We all know that *anyone* can edit Wikipedia, regardless of their level of
knowledge of the subject matter, so why treat the Wiki like some kind of
oracle? It's only as good as the last person to edit it. If that was
someone who happens to know his or her stuff, you get good information. And
if it wasn't, you get bad information.

So the question a Wiki reader has to ask himself is: "do I feel lucky?"

Perhaps.
 
R

Richard Heathfield

malc said:

Then again taking less than a half of a sentence and using that as an
appeal to authority is not a right thing to do.

I suppose you could view it in that light, but I was simply using Knuth's
words because they conveyed, pithily and effectively, a point that I myself
wanted to make, and of course I ascribed them to the man whom I believed
(and believe) to be their author because, well, one does, doesn't one?
 
J

J. J. Farrell

I was told that in case 3) "i" is accessed once and modified once;
in case 4) "i" is accessed twice and modified once.

I recommend you stop listening to whoever told you that.
Someone else could hopefully say if it is true and what it means in reality.

It may be true, the compiler's free to implement it that way if it
likes. It's also free in case 3 (and in the other cases) to read it 20
times and write it 43 times if it so chooses. Any compiler which
generates significantly different code for these four statements is of
very poor quality. They should all compile to the same code sequence,
which increments i using whatever sequence of operations is most
efficient.
 
P

pete

J. J. Farrell said:
I recommend you stop listening to whoever told you that.

I disagree.
It may be true,

It is true.
They should all compile to the same code sequence,
which increments i using whatever sequence of operations is most
efficient.

That all depends on whether or not (i) is an expression
with side effects.

/* BEGIN new.c ouput */

After: array[0] = 0; array[1] = 7; counter = 0; ++i;

i is 7
array[0] is 1
array[1] is 7

After: array[0] = 0; array[1] = 7; counter = 0; i = i + 1;

i is 0
array[0] is 0
array[1] is 1

/* END new.c ouput */



/* BEGIN new.c */

#include <stdio.h>

#define i (*side_effects(array))

static unsigned counter;

int *side_effects(int *array);

int main(void)
{
int array[2];

puts("/* BEGIN new.c ouput */\n");
array[0] = 0;
array[1] = 7;
counter = 0;
++i;
printf("After: array[0] = 0;"
" array[1] = 7; counter = 0; ++i;\n\n");
printf("i is %d\n", i);
printf("array[0] is %d\n", array[0]);
printf("array[1] is %d\n\n", array[1]);
array[0] = 0;
array[1] = 7;
counter = 0;
i = i + 1;
printf("After: array[0] = 0;"
" array[1] = 7; counter = 0; i = i + 1;\n\n");
printf("i is %d\n", i);
printf("array[0] is %d\n", array[0]);
printf("array[1] is %d\n", array[1]);
puts("\n/* END new.c ouput */");
return 0;
}

int *side_effects(int *array)
{
return array + counter++ % 2;
}

/* END new.c */
 
J

J. J. Farrell

pete said:
I disagree.


It is true.

It may or may not be true; the "as if" rule says so. With anything that
deserves the name of "C compiler" in the case that the OP was asking
about, it is not true.
That all depends on whether or not (i) is an expression
with side effects.

Indeed, though it's clear from the OP's posting that he was asking
about the simple case.
/* BEGIN new.c ouput */

After: array[0] = 0; array[1] = 7; counter = 0; ++i;

i is 7
array[0] is 1
array[1] is 7

After: array[0] = 0; array[1] = 7; counter = 0; i = i + 1;

i is 0
array[0] is 0
array[1] is 1

/* END new.c ouput */

In his posting, the OP defined that the end value of i is identical in
all four cases, so your example is not relevant to the question in hand.
 
P

pete

J. J. Farrell said:
It may or may not be true;
the "as if" rule says so. With anything that
deserves the name of "C compiler" in the case that the OP was asking
about, it is not true.


Indeed, though it's clear from the OP's posting that he was asking
about the simple case.

It's clear from
"I was told that in case 3) "i" is accessed once and modified once;
in case 4) "i" is accessed twice and modified once."
that what he was being told,
was taking the non simple case into account.

/* BEGIN new.c ouput */

After: array[0] = 0; array[1] = 7; counter = 0; ++i;

i is 7
array[0] is 1
array[1] is 7

After: array[0] = 0; array[1] = 7; counter = 0; i = i + 1;

i is 0
array[0] is 0
array[1] is 1

/* END new.c ouput */

In his posting, the OP defined that the end value of i is identical in
all four cases,
so your example is not relevant to the question in hand.

In the example I that gave
the value of i was 1, prior to ++i, and
the value of i was 1, prior to i = i + 1.
 

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,781
Messages
2,569,615
Members
45,294
Latest member
LandonPigo

Latest Threads

Top