difference between *ptr++ and ++*ptr ?

J

Jason

Hello,

could someone explain the difference to me inbetween:
*ptr++ and ++*ptr

Thankx a lot..

Jason.
 
E

Eric Sosman

Jason said:
Hello,

could someone explain the difference to me inbetween:
*ptr++ and ++*ptr

*ptr++ means "Fetch the thing that `ptr' points to, and
increment `ptr' so it points to the next thing."

++*ptr means "Increment the thing `ptr' points to, and
leave `ptr' itself unchanged."
 
A

August Karlstrom

Eric said:
*ptr++ means "Fetch the thing that `ptr' points to, and
increment `ptr' so it points to the next thing."

++*ptr means "Increment the thing `ptr' points to, and
leave `ptr' itself unchanged."

The second expression is unambiguous even if you don't remember the
precedence rules or evaluation order. When it comes to the first
expression I'd increment ptr in a separate statement (even though most C
programmers love multiple side-effects).


-- August
 
J

Jason

The second expression is unambiguous even if you don't remember the
precedence rules or evaluation order. When it comes to the first
expression I'd increment ptr in a separate statement (even though most C
programmers love multiple side-effects).

-- August

Ok - Thank you for the answers

Jason.S.
 
C

CBFalconer

B

Ben Pfaff

August Karlstrom said:
The second expression is unambiguous even if you don't remember the
precedence rules or evaluation order. When it comes to the first
expression I'd increment ptr in a separate statement (even though most
C programmers love multiple side-effects).

Each of *ptr++ and ++*ptr has only a single side effect.
 
C

Chris Dollin

August said:
The second expression is unambiguous even if you don't remember the
precedence rules or evaluation order. When it comes to the first
expression I'd increment ptr in a separate statement (even though most C
programmers love multiple side-effects).

`*ptr++` is the standard C idiom for fetch-and-advance-pointer.
Incrementing in a separate statement is likely to make the code more
confusing, I'd have thought.
 
P

pete

August said:
The second expression is unambiguous even if you don't remember the
precedence rules or evaluation order.

There is no evaluation order.
Assignment is not a sequence point.

This expression
*ptr++
has a value and a side effect.
The side effect is that ptr is incremented.
The value of the expression is the value of what ptr points to,
prior to being incremented,
but that evaluation can be made before
or after the side effect takes place.
 
A

August Karlstrom

Ben said:
> Each of *ptr++ and ++*ptr has only a single side effect.

Correct. When `*ptr++' (as well as `++*ptr') is part of a statement
(with assignment, procedure calls etc.) though, it (the statement) will
most likely have multiple side effects. The expression `*ptr++' as
opposed to `++*ptr' doesn't make sense as a single statement (why would
you want to dereference the pointer if you don't use it).

-- August
 
A

August Karlstrom

Chris said:
`*ptr++` is the standard C idiom for fetch-and-advance-pointer.
Incrementing in a separate statement is likely to make the code more
confusing, I'd have thought.

Confusing for the programmer who only has experience with C/C++, maybe.
In almost any other language (procedural at the statement level) the
incrementation is a separate statement.

-- August
 
C

Chris Croughton

Confusing for the programmer who only has experience with C/C++, maybe.
In almost any other language (procedural at the statement level) the
incrementation is a separate statement.

Wenn mann in Deutsch sprache, es machts nicht das in Englisch verstanden
Sie es nicht.

Quand on parle en Francais, ce ne fait rein qeu les les idiomes ne sont
pas les idiomes d'Anglais.

If one is writing in C one should use C idiom, not Fortran idiom or Ada
idiom. The C idiom is x = *ptr++, it doesn't matter that in COBOL I'd
write something like MOVE X FROM ARRAY INDEXED BY I. ADD 1 TO I. Or
that in assembler I'd write:

mov bx, i[bp]
mov x, [bx]
inc i[bp]

[Note: my German and French knowledge are about the same level as my
Fortran and COBOL by this time, which is the point. If I were writing
Fortran/speaking German primarily then I would probably have problems
understanding C/English idiom; if I write C/speak English primarily then
I have no problem with C/English idiom but do with that of other
languages...]

(And I have as little memory of whether 'idiomes' is correct French as
whether MOVE is correct COBOL...)

Chris C
 
B

Ben Pfaff

August Karlstrom said:
Correct. When `*ptr++' (as well as `++*ptr') is part of a statement
(with assignment, procedure calls etc.) though, it (the statement)
will most likely have multiple side effects. The expression `*ptr++'
as opposed to `++*ptr' doesn't make sense as a single statement (why
would you want to dereference the pointer if you don't use it).

In my experience these kinds of expressions are often used as
parts of `if' or `switch' conditionals that most often have only
a single side effect (if any). Sometimes, yes, they are part of,
e.g., assignments that will then have multiple side effects.
 
A

August Karlstrom

Chris said:
Confusing for the programmer who only has experience with C/C++, maybe.
In almost any other language (procedural at the statement level) the
incrementation is a separate statement.


Wenn mann in Deutsch sprache, es machts nicht das in Englisch verstanden
Sie es nicht.

Quand on parle en Francais, ce ne fait rein qeu les les idiomes ne sont
pas les idiomes d'Anglais.

If one is writing in C one should use C idiom, not Fortran idiom or Ada
idiom. The C idiom is x = *ptr++, it doesn't matter that in COBOL I'd
write something like MOVE X FROM ARRAY INDEXED BY I. ADD 1 TO I. Or
that in assembler I'd write:

mov bx, i[bp]
mov x, [bx]
inc i[bp]

[Note: my German and French knowledge are about the same level as my
Fortran and COBOL by this time, which is the point. If I were writing
Fortran/speaking German primarily then I would probably have problems
understanding C/English idiom; if I write C/speak English primarily then
I have no problem with C/English idiom but do with that of other
languages...]

(And I have as little memory of whether 'idiomes' is correct French as
whether MOVE is correct COBOL...)

Sure there are idioms in C, but the language is not exactly known for
putting the programmer into a straitjacket. It allows you to do pretty
much what you want. With the preprocessor you can even define a new
language ;-)

-- August
 
C

Chris Dollin

August said:
Confusing for the programmer who only has experience with C/C++, maybe.

No; confusing for the C programmer reading C code.
In almost any other language (procedural at the statement level) the
incrementation is a separate statement.

In almost any other language, there are different idioms. One uses
the idioms of the language one is using to the extent one can. If
one deliberately avoids the usual idioms, one had better have a
better reason for it than "but I can't do it that way in Prolog [1]!".

[1] Clearly, since Prolog starts with a capital letter (P for Paris),
it's a variable, and can be replaced by any value that makes the
statement true. No?
 
C

Chris Croughton

Chris said:
Chris Dollin wrote:

`*ptr++` is the standard C idiom for fetch-and-advance-pointer.
Incrementing in a separate statement is likely to make the code more
confusing, I'd have thought.

Confusing for the programmer who only has experience with C/C++, maybe.
In almost any other language (procedural at the statement level) the
incrementation is a separate statement.

If one is writing in C one should use C idiom, not Fortran idiom or Ada
idiom. The C idiom is x = *ptr++, it doesn't matter that in COBOL I'd
write something like MOVE X FROM ARRAY INDEXED BY I. ADD 1 TO I. Or
that in assembler I'd write:

mov bx, i[bp]
mov x, [bx]
inc i[bp]

Sure there are idioms in C, but the language is not exactly known for
putting the programmer into a straitjacket. It allows you to do pretty
much what you want. With the preprocessor you can even define a new
language ;-)

You can indeed (see a thread recently (somewhen in the last several
months, anyway) about someone doing just that), but anyone who finds
*ptr++ confusing is no more a "C programmer" than I am a "French
novelist". If you don't know the idioms then you don't know the
language. You /can/ write ptr = ptr + 1; instead of ++ptr if you want
(in some early compilers the forms ++i, i =+ 1 and i = i + 1 actually
generated different code deliberately), but any C programmer should be
equally at ease with any of them

Having the increment separate often loses some of the readability of the
language. Compare:

*ptr++ = a;
*ptr++ = b;
*ptr-- = c;
*ptr++ = d;

with:

*ptr = a;
++ptr;
*ptr = b;
++ptr;
*ptr = c;
--ptr;
*ptr = d;
++ptr;

The former is obvious (to any C programmer), the latter is visually
confusing and harder to maintain. Note "visually confusing", it's not
confusing to a C or C++ programmer as a concept, it is confusing to the
eye. There's a mistake in them which is visually obvious in the first
but not in the second. Merging lines:

*ptr = a; ++ptr;
*ptr = b; ++ptr;
*ptr = c; --ptr;
*ptr = d; ++ptr;

makes that mistake more obvious again, but makes maintenance messier
when 'b' becomes 'fred' and you need to line up the others.

Chris C
 
A

August Karlstrom

Chris said:
Chris said:
On Mon, 16 May 2005 14:55:53 GMT, August Karlstrom


Chris Dollin wrote:


`*ptr++` is the standard C idiom for fetch-and-advance-pointer.
Incrementing in a separate statement is likely to make the code more
confusing, I'd have thought.

Confusing for the programmer who only has experience with C/C++, maybe.
In almost any other language (procedural at the statement level) the
incrementation is a separate statement.

If one is writing in C one should use C idiom, not Fortran idiom or Ada
idiom. The C idiom is x = *ptr++, it doesn't matter that in COBOL I'd
write something like MOVE X FROM ARRAY INDEXED BY I. ADD 1 TO I. Or
that in assembler I'd write:

mov bx, i[bp]
mov x, [bx]
inc i[bp]

Sure there are idioms in C, but the language is not exactly known for
putting the programmer into a straitjacket. It allows you to do pretty
much what you want. With the preprocessor you can even define a new
language ;-)


You can indeed (see a thread recently (somewhen in the last several
months, anyway) about someone doing just that), but anyone who finds
*ptr++ confusing is no more a "C programmer" than I am a "French
novelist". If you don't know the idioms then you don't know the
language. You /can/ write ptr = ptr + 1; instead of ++ptr if you want
(in some early compilers the forms ++i, i =+ 1 and i = i + 1 actually
generated different code deliberately), but any C programmer should be
equally at ease with any of them

Having the increment separate often loses some of the readability of the
language. Compare:

*ptr++ = a;
*ptr++ = b;
*ptr-- = c;
*ptr++ = d;

with:

*ptr = a;
++ptr;
*ptr = b;
++ptr;
*ptr = c;
--ptr;
*ptr = d;
++ptr;

The former is obvious (to any C programmer), the latter is visually
confusing and harder to maintain. Note "visually confusing", it's not
confusing to a C or C++ programmer as a concept, it is confusing to the
eye. There's a mistake in them which is visually obvious in the first
but not in the second. Merging lines:

*ptr = a; ++ptr;
*ptr = b; ++ptr;
*ptr = c; --ptr;
*ptr = d; ++ptr;

makes that mistake more obvious again, but makes maintenance messier
when 'b' becomes 'fred' and you need to line up the others.

There are various reasons why you want to or have to program in C.
Expressions involving increment and decrement operators can get
arbitrarily complex and the "cleverer" the programmer the harder it will
be to maintain the code.

The example above can be translated to

ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
ptr[1] = d;
ptr++;

which clearly shows that the second statement is superfluous so the
statement sequence can be rewritten as

ptr[0] = a;
ptr[1] = d;
ptr[2] = c;
ptr++;

The compiler will then probably optimize the code to make it as fast as
before. Which version do you think is more readable?

Note that I have nothing against the increment/decrement operator if it
is used in a single statement.


-- August
 
M

Michael Mair

August said:
Chris said:
Chris Croughton wrote:

On Mon, 16 May 2005 14:55:53 GMT, August Karlstrom

Chris Dollin wrote:

`*ptr++` is the standard C idiom for fetch-and-advance-pointer.
Incrementing in a separate statement is likely to make the code more
confusing, I'd have thought.

Confusing for the programmer who only has experience with C/C++,
maybe. In almost any other language (procedural at the statement
level) the incrementation is a separate statement.

If one is writing in C one should use C idiom, not Fortran idiom or Ada
idiom. The C idiom is x = *ptr++, it doesn't matter that in COBOL I'd
write something like MOVE X FROM ARRAY INDEXED BY I. ADD 1 TO I. Or
that in assembler I'd write:

mov bx, i[bp]
mov x, [bx]
inc i[bp]

Sure there are idioms in C, but the language is not exactly known for
putting the programmer into a straitjacket. It allows you to do
pretty much what you want. With the preprocessor you can even define
a new language ;-)

You can indeed (see a thread recently (somewhen in the last several
months, anyway) about someone doing just that), but anyone who finds
*ptr++ confusing is no more a "C programmer" than I am a "French
novelist". If you don't know the idioms then you don't know the
language. You /can/ write ptr = ptr + 1; instead of ++ptr if you want
(in some early compilers the forms ++i, i =+ 1 and i = i + 1 actually
generated different code deliberately), but any C programmer should be
equally at ease with any of them

Having the increment separate often loses some of the readability of the
language. Compare:

*ptr++ = a;
*ptr++ = b;
*ptr-- = c;
*ptr++ = d;

with:

*ptr = a;
++ptr;
*ptr = b;
++ptr;
*ptr = c;
--ptr;
*ptr = d;
++ptr;

The former is obvious (to any C programmer), the latter is visually
confusing and harder to maintain. Note "visually confusing", it's not
confusing to a C or C++ programmer as a concept, it is confusing to the
eye. There's a mistake in them which is visually obvious in the first
but not in the second. Merging lines:

*ptr = a; ++ptr;
*ptr = b; ++ptr;
*ptr = c; --ptr;
*ptr = d; ++ptr;

makes that mistake more obvious again, but makes maintenance messier
when 'b' becomes 'fred' and you need to line up the others.

There are various reasons why you want to or have to program in C.
Expressions involving increment and decrement operators can get
arbitrarily complex and the "cleverer" the programmer the harder it will
be to maintain the code.

Reminds me of
"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."
(attributed to B.W. Kernighan)
:)
The example above can be translated to

ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
ptr[1] = d;
ptr++;

which clearly shows that the second statement is superfluous so the
statement sequence can be rewritten as

ptr[0] = a;
ptr[1] = d;
ptr[2] = c;
ptr++;

At least as long as no "volatile" is hanging around for fun...

The compiler will then probably optimize the code to make it as fast as
before. Which version do you think is more readable?

Honestly, for me both is the same.
I use whatever expresses the way _I_ think about the task the
code performs. As soon as I have to explain some sort of "cleverness"
in more than half a line, I go for a more readable way of writing
the code.

Note that I have nothing against the increment/decrement operator if it
is used in a single statement.

This is in my case one of the rarer uses (apart from the increment part
of for). In single statements, I do not need the side effect as a side
effect but as "main effect", so I can as well express it by += 1.


Cheers
Michael
 
C

Chris Croughton

There are various reasons why you want to or have to program in C.
Expressions involving increment and decrement operators can get
arbitrarily complex and the "cleverer" the programmer the harder it will
be to maintain the code.

So ban all complex expressions, just like MS Word tries to do with
complex sentences. "C program." "C program run." "Run, program, run!"
"I said run, dammit, not crash the OS!"
The example above can be translated to

ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
ptr[1] = d;
ptr++;

Wrong: in the example ptr is incremented three times and decremented
once, so it should be ptr += 2;

But anyway, I said that there was a mistake: the -- should have been a
++ which was what was 'obvious' when looking at the first version (why
was one of them different?). Indeed, I said that it was a mistake
several times. And it's something which is not as obvious with the
increment on a different line.

But your 'translation' is not necessarily the same anyway. Some of the
*ptr++ = whatever statements might be conditional so absolute offsets
aren't applicable.

Make each of them conditional:

if (a) *ptr++ = a;
if (b) *ptr++ = b;
if (c) *ptr-- = c;
if (d) *ptr++ = d;

And you can no longer do your 'translation'.
which clearly shows that the second statement is superfluous

But what it misses is that the second one is /wrong/.
 
A

August Karlstrom

Chris said:
There are various reasons why you want to or have to program in C.
Expressions involving increment and decrement operators can get
arbitrarily complex and the "cleverer" the programmer the harder it will
be to maintain the code.


So ban all complex expressions, just like MS Word tries to do with
complex sentences. "C program." "C program run." "Run, program, run!"
"I said run, dammit, not crash the OS!"

The example above can be translated to

ptr[0] = a;
ptr[1] = b;
ptr[2] = c;
ptr[1] = d;
ptr++;


Wrong: in the example ptr is incremented three times and decremented
once, so it should be ptr += 2;

But anyway, I said that there was a mistake: the -- should have been a
++ which was what was 'obvious' when looking at the first version (why
was one of them different?). Indeed, I said that it was a mistake
several times. And it's something which is not as obvious with the
increment on a different line.

But your 'translation' is not necessarily the same anyway. Some of the
*ptr++ = whatever statements might be conditional so absolute offsets
aren't applicable.

Make each of them conditional:

if (a) *ptr++ = a;
if (b) *ptr++ = b;
if (c) *ptr-- = c;
if (d) *ptr++ = d;

And you can no longer do your 'translation'.

which clearly shows that the second statement is superfluous


But what it misses is that the second one is /wrong/.

Sorry, I missed the deliberate nature of the bug in your example.

If your latest example was written as

int i, tests[4] = {a, b, c, d};

for (i = 0; i < 4; i++) if (tests) ptr = tests;
/* Use the value of i instead of incrementing `ptr'. */

in the first place there would be no such bug. Okay, the above is
slightly less efficient, but probably it won't matter, it all depends on
the situation. See the answers to the clc posting "wrinting an optimised
code" by junky_fellow 17 of May.

-- August
 
C

Chris Torek

(where "*ptr--" is a bug because it should read "*ptr++")

Sorry, I missed the deliberate nature of the bug in your example.

If your latest example was written as

int i, tests[4] = {a, b, c, d};

for (i = 0; i < 4; i++) if (tests) ptr = tests;
/* Use the value of i instead of incrementing `ptr'. */

in the first place there would be no such bug. Okay, the above is
slightly less efficient, but probably it won't matter ...


It produces a different result, which probably *does* matter. :)

The sample code "compresses out zeros" (once one fixes the *ptr--).
The rewrite does not compress out zeros, instead leaving ptr
unchanged when tests==0.

A correct array rewrite of the corrected code might read:

for (i = j = 0; i < 4; i++)
if (tests != 0)
ptr[j++] = tests;

though of course this leaves "ptr" unchanged. (If we want ptr to
advance, just add "ptr += j" after the loop -- or just change the
loop to write on *ptr++ in the first place, eliminating j entirely.)

The important thing, in all of this, is really that "*ptr++" is a
pretty common idiom in C, so one should get to know it if one is
to do much C programming. The sequence "*p++ = val" "means" "update
the array element to which p points, and also update p to point to
the next array element", while "x = *p++" "means" "fetch the array
element to which p points, and also update p to point to the next
array element". Of course, it also becomes important to understand
sequence points, because the "updating" happens "between the previous
and next sequence point", and variables that will be updated must
be left alone (for their new values to settle in) until that next
sequence point has occurred.
 

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,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top