simple pointer question

L

lokman

Hi,

In the following code, can someone tell me the difference between *p++ and
p++ ? I can see both achieve the same result.

Thanks a lot !




#include <iostream>
using namespace::std;
int main() {
char *p = "test pointer";
while (*p) {
cout << *p;
*p++; // <<- What is the difference between *p++ and p++ (both achieve
the same result) ?
}
cout << endl;
return 0;
}
 
J

Jakob Bieling

*p++; // <<- What is the difference between *p++ and p++ (both achieve
the same result) ?

p ++ increments the pointer, like you expect. *p ++ first dereferences
the pointer, and then increments it. Since the dereferenced temporary is not
assigned to anything, it is discarded.

hth
 
A

ak

in this context there is no diff.

if you would for instance do a cout << *p++
then it would print p's current char and then
incr the ptr

*p get the value from the ptr
++ incr the ptr with whatever size of type it is.

/ak
 
F

Frane Roje

lokman said:
Hi,

In the following code, can someone tell me the difference between *p++ and
p++ ? I can see both achieve the same result.

Thanks a lot !

Ok,
p++ increments the pointer
*p gets the contents of the variable to which the pointer is pointing to

You could write in your loop
cout<<*p++<<endl;

Because of the precedence of the * operator so the *p is done before p++,
maybe it would be more clear if you wrote (*p)++ (don't use this in coding
this is just for you to understand you should write *p++ in your code)

Maybe an example of copying two strings;

char *s1="test";
char *s2="blab";

for(unsigned int i=0;i<strlen(s1);i++)
*s1++=*s2++;

So the content of the s1 becomes the content of the s2;
Note that they are both the same size, if not you might have
undefined behavior.
But if you want to copy strign I would reccomed using <string>
rather than char*.

HTH


--
Frane Roje

Have a nice day

Remove (*dele*te) from email to reply
 
K

Kevin Goodsell

lokman said:
Hi,

In the following code, can someone tell me the difference between *p++ and
p++ ? I can see both achieve the same result.

Thanks a lot !


#include <iostream>
using namespace::std;
int main() {
char *p = "test pointer";

Quick note: don't do this. Never make a (non-const) char pointer point
to a string literal. This conversion is allowed for C compatibility, but
is deprecated because it is dangerous. It allows you to write code that
(attempts to) modify a string literal without getting a warning from the
compiler. Modifying a string literal (or attempting to) invokes
undefined behavior.

If you want a pointer to a string literal, always use a pointer to const
char, like one of the following:

const char *p = "some string";
char const *p = "some string"; // same as prev

const char * const p = "some string";
char const * const p = "some string"; // same as prev

In the last two 'p' itself is also const.
while (*p) {
cout << *p;
*p++; // <<- What is the difference between *p++ and p++ (both achieve
the same result) ?
}
cout << endl;
return 0;
}

It looks like all the replies so far are wrong in one way or another.
The expression 'p++' causes p to be incremented at some point before the
next sequence point. It also has a result, which is the value of 'p'
before being incremented. There's an subtle but important point here:
you don't know *when* 'p' will actually be updated, only that it will
happen sometime before the next sequence point (usually a semi-colon,
but there are others). People frequently get this wrong.

As for the expression '*p++', it is equivalent to '*(p++)' (contrary to
what one of the other replies said, post-increment has higher precedence
than dereference -- check any precedence chart). So, as described
previously, 'p' is scheduled to be incremented at some point before the
next sequence point, and also a result is given. The result is the value
of 'p' prior to the increment. The '*' is applied to that, giving the
object that 'p' pointed to prior to the increment. This result is
immediately discarded in your case.

So there's no reason for the '*' in this case. It might even slow your
program down a little, so get rid of it.

Also, replace 'p++' with '++p'. Get in the habit of using pre-increment
in cases where either will work. There's a chance it will be faster, and
it almost certainly won't be slower. There probably is no difference for
built-in types, but for class types there may be a substantial difference.

-Kevin
 
K

Kevin Goodsell

Jakob said:
p ++ increments the pointer, like you expect. *p ++ first dereferences
the pointer, and then increments it.

Nitpick: That sequence of events is not required.

-Kevin
 
K

Kevin Goodsell

Frane said:
Ok,
p++ increments the pointer
*p gets the contents of the variable to which the pointer is pointing to

Actually it gets the variable itself. "Contents of" sounds like a copy.
You could write in your loop
cout<<*p++<<endl;

Because of the precedence of the * operator so the *p is done before p++,
maybe it would be more clear if you wrote (*p)++ (don't use this in coding
this is just for you to understand you should write *p++ in your code)

(*p)++ has a completely different meaning than *p++.
Maybe an example of copying two strings;

char *s1="test";
char *s2="blab";

Make these const char *.
for(unsigned int i=0;i<strlen(s1);i++)
*s1++=*s2++;

This is wrong or otherwise ill-advised in several ways.

1) The technically correct type to use is size_t.

2) Recalculating the length on each iteration is unnecessarily inefficient.

3) Prefer pre-increment to post-increment.

4) Modifying a string literal (which is a const object) gives undefined
behavior.

Besides that, the general approach is definitely not correct in general.
You'd need to check the relative length of the source string against the
available length of the destination buffer, then loop based on the
source string. If you knew the destination length was adequate, you
could just do this:

while (*dest++ = *src++) { continue; }

-Kevin
 
K

Kevin Goodsell

Benoit said:
Would you find this one less readable ?

while (*dest++ = *src++) ;

I find it less clear. A semi-colon in a place where they aren't usually
seen can be easily missed, making the reader think that the 'while'
controls (or is supposed to control) some statement that follows. It can
also look like an error, as if the programmer added the semi-colon at
the end of the line out of habit.

An explicit 'continue' statement removes all doubt about the intent.

-Kevin
 
F

Frane Roje

Kevin Goodsell said:
Frane Roje wrote:
(*p)++ has a completely different meaning than *p++.
How?


Make these const char *.
if they were const wouldn't that make then disabled for any kind of change?
This is wrong or otherwise ill-advised in several ways.

What is advised?(exepct for strcpy(), or maybe strncpy()(I'm not sure if
this one
exists))
1) The technically correct type to use is size_t.
Isn't size_t actualy an unsigned integer?
3) Prefer pre-increment to post-increment. Why?


Besides that, the general approach is definitely not correct in general.
You'd need to check the relative length of the source string against the
available length of the destination buffer, then loop based on the
source string. If you knew the destination length was adequate, you
could just do this:

--
Frane Roje

Have a nice day

Remove (*dele*te) from email to reply
 
J

Jakob Bieling

Frane Roje said:

Consider the following:

char test[] = "Hello";
char* p = test;

char t = *p ++;
char s = (*p) ++;

Now think about which values 's' and 't' will hold ..
if they were const wouldn't that make then disabled for any kind of
change?

Right, because changing what they are pointing at is wrong. String
literals are constant, which is why you should use 'char const*' instead of
'char*' to enforce this constantness. See Kevin's reply to the OP for more
about this.
What is advised?(exepct for strcpy(), or maybe strncpy()(I'm not sure if
this one
exists))

Isn't size_t actualy an unsigned integer?

Not necessarily in all implementations.

Post-increment means:
1) Copy current value to temporary
2) Increment
3) Return the temporary from 1

Pre-increment means:
1) Increment:
2) Return self

So you see, pre-increment does the same (in your case), but does it
faster, ie. definitely not slower. There are cases where you actually do
need to post-increment, but in all others, prefer pre-increment. But again,
see Kevin's reply to the OP's message ;)

regards
 
K

Kevin Goodsell

Frane said:

Uh... Well, the former increments the thing pointed to and returns the
un-incremented value. The later increments the pointer and returns the
thing it pointed to before the increment.
if they were const wouldn't that make then disabled for any kind of change?

That's the idea. Any change causes undefined behavior, so preventing it
is a Good Thing.
What is advised?(exepct for strcpy(), or maybe strncpy()(I'm not sure if
this one
exists))



Isn't size_t actualy an unsigned integer?

Yes, but not necessarily unsigned int.

Because it may be faster and is very unlikely to be slower.

-Kevin
 
D

DaKoadMunky

'p' is scheduled to be incremented at some point before the
next sequence point

If 'p' is a user defined type would the point of incrementation be
well-defined?

It seems like it would be given that it is a function call, but I am not sure.





Brian F. Seaberg
Naperville, Illinois
Delray Beach, Florida
 
V

Victor Bazarov

DaKoadMunky said:
If 'p' is a user defined type would the point of incrementation be
well-defined?

It seems like it would be given that it is a function call, but I am not
sure.

You are correct. Some elements of C++ do offer "work-arounds" for
undefined behaviour. However, relying on them means building bad
habits...

V
 
L

lokman

Hi and thanks for the great help.

I have modified the simple code a little bit based on the reply.

And I have a question again. I know that instead of using pointer
arithmetic, I can access individual characters in this way: e.g. cout <<
p[5]; This will simply print the 5th character in the character array.
(Correct me if I am wrong please.).

My question is: Can someone please tell me what is the reason that if I do:
cout << p[5] << endl; before the while loop, it prints the charater "p", as
expected. But somehow, after the while loop, if I do : cout << p[5] << endl;
again, it cannot print the "p" character anymore.

Thanks a lot again.


// Code starts below.
#include <iostream>

using namespace::std;

int main() {

const char *p = "test pointer";

cout << p[5] << endl; // New piece of code

while (*p) { cout << *p; ++p;} // Modified ! I understand ++pp is a good
practice now, thanks !!
cout << endl;

cout << p[5] << endl; // New piece of code

return 0;
}
 
J

Jakob Bieling

lokman said:
Hi and thanks for the great help.

I have modified the simple code a little bit based on the reply.

And I have a question again. I know that instead of using pointer
arithmetic, I can access individual characters in this way: e.g. cout <<
p[5]; This will simply print the 5th character in the character array.
(Correct me if I am wrong please.).

It will actually print the 6th character .. p [0] prints the first, p
[1] prints the second and so on
My question is: Can someone please tell me what is the reason that if I do:
cout << p[5] << endl; before the while loop, it prints the charater "p", as
expected. But somehow, after the while loop, if I do : cout << p[5] << endl;
again, it cannot print the "p" character anymore.

Thanks a lot again.


// Code starts below.
#include <iostream>

using namespace::std;

int main() {

const char *p = "test pointer";

cout << p[5] << endl; // New piece of code

while (*p) { cout << *p; ++p;} // Modified ! I understand ++pp is a good

Above you modifiy the pointer, ie the address it is pointing to.
practice now, thanks !!
cout << endl;

cout << p[5] << endl; // New piece of code

That means, that in the line above, p [5] means something different than
the p [5] before the loop, because the value of p is different.
return 0;
}

hth
 
F

Frane Roje

Now think about which values 's' and 't' will hold ..

Yes I tried this code and it behaved correctly, I mean the out put
is
H e
But then I didn't know what was the difference so I did a little bit
different code:
char test[]="Hello";

char* p = test;

char t = *p++;

char s = (*p)++;

char u = (*p)++;

Now this outputs(remember the string is "Hello"):

H e f

So I was confused and did another test:

char test[]="Hello";

char* p = test;

char t = (*p)++;

char s = (*p)++;

char u = (*p)++;

And this outputs:

H I J

And I'm still confused, it seems like it outputs the alphabetically next
character.

I don't get it. Could someone clarify this?
Not necessarily in all implementations.
So to be techically correct I should use size_t rather than unsigned int?

--
Frane Roje

Have a nice day

Remove (*dele*te) from email to reply
 
L

lokman

Thanks !

I now understand that: During the while loop, pointer p is keep on changing
its memory address from the initial one which is point to character 't', up
to '\0'. That is the reason why after the while loop, if I put the statement
cout << p[5];, nothing will be return.

In odder to have point p to point to the start of the "test pointer"
characters, does it mean that I have to traverse p all the way back to where
it is pointing to initially (doesn't seem to work as I tested and doesn't
sound like a good practice) or should I reinitialize the p to point to "test
pointer again" ?


Actually, I have modified the previous code to become a version where I can
guarantee to get char number 6 before and after the while loop, please give
some comment.

Thanks a lot.


#include <iostream>

using namespace::std;

int main() {

char chr[] = "test pointer";
const char *p = chr; // constant character pointer to avoid chr[] content
being change

cout << p[5] << endl; // this prints p
cout << chr[5] << endl; // this prints p too !

while (*p) { cout << *p; ++p;}
cout << endl;

cout << chr[5] << endl; // this prints p after the while loop
cout << p[5] << endl; // this doesn't print the 6th char anymore

return 0;

}





Jakob Bieling said:
lokman said:
Hi and thanks for the great help.

I have modified the simple code a little bit based on the reply.

And I have a question again. I know that instead of using pointer
arithmetic, I can access individual characters in this way: e.g. cout <<
p[5]; This will simply print the 5th character in the character array.
(Correct me if I am wrong please.).

It will actually print the 6th character .. p [0] prints the first, p
[1] prints the second and so on
My question is: Can someone please tell me what is the reason that if I do:
cout << p[5] << endl; before the while loop, it prints the charater "p", as
expected. But somehow, after the while loop, if I do : cout << p[5] << endl;
again, it cannot print the "p" character anymore.

Thanks a lot again.


// Code starts below.
#include <iostream>

using namespace::std;

int main() {

const char *p = "test pointer";

cout << p[5] << endl; // New piece of code

while (*p) { cout << *p; ++p;} // Modified ! I understand ++pp is a
good

Above you modifiy the pointer, ie the address it is pointing to.
practice now, thanks !!
cout << endl;

cout << p[5] << endl; // New piece of code

That means, that in the line above, p [5] means something different than
the p [5] before the loop, because the value of p is different.
return 0;
}

hth
 
D

David Riebenbauer

* Frane Roje said:
Yes I tried this code and it behaved correctly, I mean the out put
is
H e
But then I didn't know what was the difference so I did a little bit
different code:
Ok, so let's look at what this does exactly.
char test[]="Hello";

char* p = test;
Now p holds the address of the first char in test.
char t = *p++;
If you would have braces in here this would look something like this:
char t = *(p++);
First p is dereferenced and assigned to t.
Afterwards p is incremented by the length of one char.
So now it holds the address of the second char of test, which is 'e'.
char s = (*p)++;
As before first the value p points to is assigned to s.
But now the value p points to is incremented, instead of p itself.
So you modify test directly, which now holds "Hfllo".
char u = (*p)++;
Same as before but as test is modified yoiu get 'f';
After this line test should be "Hgllo"
Now this outputs(remember the string is "Hello"):

H e f

So I was confused and did another test:
This should also become clear now.
char test[]="Hello";

char* p = test;

char t = (*p)++; Iello

char s = (*p)++; Jello

char u = (*p)++; Kello

And this outputs:

H I J

And I'm still confused, it seems like it outputs the alphabetically next
character.

I don't get it. Could someone clarify this?
Hope i succeeded.

David
 
F

Frane Roje

Yes you made it clear.
It seems I've learned something wrong and it would be very bad if I hadn't
found it now and then years later did.
Anyway thanx

--
Frane Roje

Have a nice day

Remove (*dele*te) from email to reply
 

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,481
Members
44,900
Latest member
Nell636132

Latest Threads

Top