simple pointer question

Discussion in 'C++' started by lokman, Apr 17, 2004.

  1. lokman

    lokman Guest

    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;
    }
     
    lokman, Apr 17, 2004
    #1
    1. Advertising

  2. "lokman" <> wrote in message
    news:c5rdrn$a7h$...

    > *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
    --
    jb

    (replace y with x if you want to reply by e-mail)
     
    Jakob Bieling, Apr 17, 2004
    #2
    1. Advertising

  3. lokman

    ak Guest

    On Sat, 17 Apr 2004 23:10:00 +0900, "lokman" <> wrote:

    >>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;
    >>}
    >>


    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
     
    ak, Apr 17, 2004
    #3
  4. lokman

    Frane Roje Guest

    "lokman" <> wrote in message
    news:c5rdrn$a7h$...
    > 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
     
    Frane Roje, Apr 17, 2004
    #4
  5. lokman wrote:

    > 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
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Apr 17, 2004
    #5
  6. Jakob Bieling wrote:

    > "lokman" <> wrote in message
    > news:c5rdrn$a7h$...
    >
    >
    >> *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.


    Nitpick: That sequence of events is not required.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Apr 17, 2004
    #6
  7. Frane Roje wrote:

    > "lokman" <> wrote in message
    > news:c5rdrn$a7h$...
    >
    >>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


    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
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Apr 17, 2004
    #7

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


    Would you find this one less readable ?

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

    Benoit
     
    Benoit Mathieu, Apr 17, 2004
    #8
  9. Benoit Mathieu wrote:

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

    >
    >
    > 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
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Apr 17, 2004
    #9
  10. lokman

    Frane Roje Guest

    "Kevin Goodsell" <> wrote in message
    news:rifgc.14914$...
    > Frane Roje wrote:


    > (*p)++ has a completely different meaning than *p++.


    How?

    > > Maybe an example of copying two strings;
    > >
    > > char *s1="test";
    > > char *s2="blab";

    >
    > Make these const char *.

    if they were const wouldn't that make then disabled for any kind of change?

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

    >
    > 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
     
    Frane Roje, Apr 17, 2004
    #10
  11. "Frane Roje" <frane.roje(*dele*te)@st.htnet.hr> wrote in message
    news:c5s2jq$qvk$...
    > "Kevin Goodsell" <> wrote in message
    > news:rifgc.14914$...
    > > Frane Roje wrote:

    >
    > > (*p)++ has a completely different meaning than *p++.

    >
    > How?


    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 ..

    > > > Maybe an example of copying two strings;
    > > >
    > > > char *s1="test";
    > > > char *s2="blab";

    > >
    > > Make these const char *.

    > 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.

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

    > >
    > > 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?


    Not necessarily in all implementations.

    > > 3) Prefer pre-increment to post-increment.

    > Why?


    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
    --
    jb

    (replace y with x if you want to reply by e-mail)
     
    Jakob Bieling, Apr 17, 2004
    #11
  12. Frane Roje wrote:

    > "Kevin Goodsell" <> wrote in message
    > news:rifgc.14914$...
    >
    >>Frane Roje wrote:

    >
    >
    >>(*p)++ has a completely different meaning than *p++.

    >
    >
    > How?


    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.

    >
    >
    >>>Maybe an example of copying two strings;
    >>>
    >>>char *s1="test";
    >>>char *s2="blab";

    >>
    >>Make these const char *.

    >
    > 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.

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

    >>
    >>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?


    Yes, but not necessarily unsigned int.

    >
    >
    >>3) Prefer pre-increment to post-increment.

    >
    > Why?


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

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Apr 17, 2004
    #12
  13. lokman

    DaKoadMunky Guest

    >'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
     
    DaKoadMunky, Apr 18, 2004
    #13
  14. "DaKoadMunky" <> wrote...
    > >'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.

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

    V
     
    Victor Bazarov, Apr 18, 2004
    #14
  15. lokman

    lokman Guest

    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;
    }




    "lokman" <> wrote in message
    news:c5rdrn$a7h$...
    > 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;
    > }
    >
    >
     
    lokman, Apr 18, 2004
    #15
  16. "lokman" <> wrote in message
    news:c5t70i$n71$...
    > 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
    --
    jb

    (replace y with x if you want to reply by e-mail)
     
    Jakob Bieling, Apr 18, 2004
    #16
  17. lokman

    Frane Roje Guest

    "Jakob Bieling" <> wrote in message
    news:c5s3km$je8$07$-online.com...

    > 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
     
    Frane Roje, Apr 18, 2004
    #17
  18. lokman

    lokman Guest

    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" <> wrote in message
    news:c5t8ce$2i4$02$-online.com...
    > "lokman" <> wrote in message
    > news:c5t70i$n71$...
    > > 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
    > --
    > jb
    >
    > (replace y with x if you want to reply by e-mail)
    >
    >
     
    lokman, Apr 18, 2004
    #18
  19. * Frane Roje <>:
    > "Jakob Bieling" <> wrote in message
    > news:c5s3km$je8$07$-online.com...
    >
    >> 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:

    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

    --
    ,' David Riebenbauer - Student at Technichal University of Graz ~~~|
    /' / /_,~""~""/ ICQ: 322056002 -\/- Playlist: |
    < /' Fernbedienung ~= Macht ,/'*','* '/ Die geht euch nichts an! |
    /\/\/\/\/\/\/\/\/\/\/\/\/\/' /)/(\ |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
     
    David Riebenbauer, Apr 18, 2004
    #19
  20. lokman

    Frane Roje Guest

    "David Riebenbauer" <> wrote in message
    news:40825ba7$0$30786$...


    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
     
    Frane Roje, Apr 18, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. overbored
    Replies:
    5
    Views:
    9,145
  2. Replies:
    10
    Views:
    704
    Chris Torek
    Feb 4, 2005
  3. jimjim
    Replies:
    16
    Views:
    844
    Jordan Abel
    Mar 28, 2006
  4. Replies:
    4
    Views:
    1,268
    Fred Zwarts
    Jul 2, 2009
  5. A
    Replies:
    7
    Views:
    639
Loading...

Share This Page