Thread: dangerous pointers

  1. #1
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751

    Post dangerous pointers

    I recently found this
    Code:
      order.c -- precedence in pointer operations */
     #include <stdio.h>
     int data[2] = {100, 200};
     int moredata[2] = {300, 400};
     int main(void)
     {
       int * p1, * p2, * p3;
     
       p1 = p2 = data;
       p3 = moredata;
       printf("  *p1 = %d,   *p2 = %d,	 *p3 = %d\n",
     		    *p1	 ,   *p2	 ,	 *p3);
       printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",
     		  *p1++	, *++p2	 , (*p3)++);
       printf("  *p1 = %d,   *p2 = %d,	 *p3 = %d\n",
     		    *p1	 ,   *p2	 ,	 *p3);
       getchar();
       return 0;
     }
    pointes already take some getting used to but then you throw these unary operators ++ and -- it just takes on even more confusion.
    My primary is at
    Code:
    printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",
     		  *p1++	, *++p2	 , (*p3)++);
    this at first glance doesn't seem harmful but when you run it, you find out that the element and value the first and last expression point to have in fact been changed and you only figure that out when you reference that element and or value again. Is that kind of crazy??? when using these operators on pointers it seems you need to have a notepad handy to keep track of what your doing. again: I can only imagine the chaos that could come from this.
    There you are happily manipulating the elements you've used those ++ and -- operators on only to reaslise they were the wrong ones all along. *shudder

    the ouput:
    Code:
      *p1 = 100,   *p2 = 100,	 *p3 = 300
     *p1++ = 100, *++p2 = 200, (*p3)++ = 300
       *p1 = 200,   *p2 = 200,	 *p3 = 301
    scary..
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  2. #2
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>you find out that the element and value the first and last expression point to have in fact been changed
    Not quite so, I'm afraid. The value of the first element of the data array (pointed to by both p1 and p2 before all the crazy bits start) remains the same throughout. Print out the array like so to see for sure:

    >>printf ("data[0] = %d, data[1] = %d\n", data[0], data[1]);


    *p++ means use the value pointed to, then increment the pointer. The data value never changes, the address the pointer is pointing to does.

    *++p means increment the pointer, then use the value pointed to. The data value never changes, the address the pointer is pointing to does.

    (*p)++ means increment the value pointed to (ie dereference first, then increment). The data value does change, the address the pointer is pointing to, doesn't.

    Clear as mud, eh!
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  3. #3
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    sorry, I wasn't really clear. I just meant the code
    Code:
    printf("*p1++ = %d, * (*p3)++ = %d\n");
    respecitvely, increment the element that *p1 is pointing to ( when you'd expect it to change the value) and the other part of the code (*p3)++ changes the value of the object *p3 is pointing to, to *object + 1.

    basically as you said
    Code:
    *p++.
    changes the address, but the value remains the same, and (*p3++), changes the value of the element. the last I don't find that confusing it seems to conform to regular pointer notation. ie
    Code:
    *(ptr + n)
    where it will return the value of
    Code:
    array[n]
    but the first, changing the address but not the value?? it doesn't compute in my head because
    Code:
     * ptr + 1
    would change the value of the object that ptr points to. And in my head the unary operators ++ and -- increment by 1 and decrement by 1 respectively. I just find the way the unary operators work on pointers not in accord with what one might expect, or has already seen.
    They were confusing at first, but adding the unary to work with them, seems to mean you have to memorize a whole set of new rules. So I'm just trying to see the laws that ties them all togather and how.

    My main concern is that you only seem to realise these on referncing that pointer again, since the ++ operators don't seem to follow the same rules. Extra confusing, least for me anyway. I hope this is a little clearer. Correct me if i'm wrong.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >seems to mean you have to memorize a whole set of new rules
    Not really, just use parentheses as a disambiguator (highly technical term) whenever you aren't sure about the precedence or associativity of an expression. You think we actually memorize those funky rules?
    My best code is written with the delete key.

  5. #5
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Quote Originally Posted by Prelude
    Not really, just use parentheses as a disambiguator (highly technical term) whenever you aren't sure about the precedence or associativity of an expression. You think we actually memorize those funky rules?
    I actually think YOU memorize them, yes!! still annoying though, since the ++ and -- and * have the same precedence expcept now you have to read them from right to left. Maybe if i was left handed it''d make sense.

    [definition]
    disambiguator - (computer science) a natural language processing application that tries to determine the intended meaning of a word or phrase by examining the linguistic context in which it is used[/definition]
    good to know.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  6. #6
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I actually think YOU memorize them, yes!!
    Nope, I use parentheses when I can't remember and I use K&R when I need to be sure. My brain cells are better used by not trying to memorize the C precedence table.

    [definition]disambiguator - (computer science) a natural language processing application that tries to determine the intended meaning of a word or phrase by examining the linguistic context in which it is used[/definition]
    Feh, I totally made that up. It's not as funny now that I know it's a real word.
    My best code is written with the delete key.

  7. #7
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >> (*p3++), changes the value of the element.
    If you are going to use parentheses, make sure you do it correctly
    I think you meant to say
    >(*p3)++
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  8. #8
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Quote Originally Posted by Hammer
    >> (*p3++), changes the value of the element.
    If you are going to use parentheses, make sure you do it correctly
    I think you meant to say
    >(*p3)++
    True, thanks.

    Can you guys critique this for me. I'm trying to make some documentation to fall back on until pointers are second nature. I've been staring at it for too long now, so a second look would be appreaciated.
    pointer notation and array notation:
    =========================================

    int *ptr - pointer to integer. allocates enough memory to store
    a variable of size integer.

    ptr = &variable
    assignes addy of variable to pointer.

    printf("%p", ptr);
    print the address of the object that ptr points to

    printf("%d", *ptr);
    print the value of the object that ptr points to

    *ptr + 1 or (*ptr) + 1
    adds 1 to the value of the object that ptr points to

    *(ptr + n) same as array[n]
    used in arrays. returns the value at array[n]. tecnically
    moves up the address of the object that ptr points to n
    times then references/returns the value there.

    ptr + 1 same as &array[1]
    used in arrays. returns the address of array[0 + 1].
    that is array[1]

    &ptr
    returns the address of the actual pointer variable itself


    *ptr++ or *(ptr++) or &array[n] + 1
    increments the address of the variable ptr points to.
    subsequently returning the value stored at array[n] + 1


    *++ptr
    moves ptr up 1 address and returns
    value at new address. so if object was *(ptr + 2) or
    array[2] would return *(ptr + 3) or array[3] where
    array[3] = value at array element 2


    (*p)++ or array[n] + 1
    increment the value ptr pointing to by 1. so same address
    but value at addy incremented by 1.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  9. #9
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >int *ptr - pointer to integer.
    Yes.

    >allocates enough memory to store a variable of size integer.
    The pointer points to memory, it doesn't allocate it. ptr is just another variable, the value it holds is an address.

    >ptr = &variable
    >assignes addy of variable to pointer.
    Yes.

    >printf("%p", ptr);
    >print the address of the object that ptr points to
    Yes, but this is undefined behavior unless ptr is defined as void *. If it isn't, you need to cast the pointer to the correct type because variable length functions won't do it for you:
    Code:
    printf("%p\n", (void *)ptr);
    You could also say that this prints the value of ptr.

    >printf("%d", *ptr);
    >print the value of the object that ptr points to
    Yes.

    >*ptr + 1 or (*ptr) + 1
    >adds 1 to the value of the object that ptr points to
    Yes.

    >*(ptr + n) same as array[n] used in arrays.
    Yes, that'll do.

    >ptr + 1 same as &array[1] used in arrays.
    Ditto.

    >&ptr
    >returns the address of the actual pointer variable itself
    Yes.

    >*ptr++ or *(ptr++) or &array[n] + 1
    >increments the address of the variable ptr points to.
    >subsequently returning the value stored at array[n] + 1
    Close, the resulting value is *ptr, or array[n], but the pointer does point to the next location in memory.

    >*++ptr
    >moves ptr up 1 address and returns value at new address.
    Yes.

    >(*p)++ or array[n] + 1
    >increment the value ptr pointing to by 1.
    Yes.
    My best code is written with the delete key.

  10. #10
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >(*p)++ or array[n] + 1
    >increment the value ptr pointing to by 1.
    Yes.
    No. This increments:
    >>(*p)++
    this doesn't:
    >>array[n] + 1
    The later only adds 1 to array[n] and returns it in a temporary int, leaving array[n] unchanged. It would be an increment if you did this though:
    >>array[n] = array[n] + 1;
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  11. #11
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >No.
    Yes. The value is indeed incremented, the modified value just isn't stored in the variable as a side effect as it is with the former construct.

    >It would be an increment if you did this though
    If you did that then it would be complete. As it is, array[n] + 1 is an incomplete expression and we really can't assume what else was meant to be a part of it, can we?
    My best code is written with the delete key.

  12. #12
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>The value is indeed incremented...
    ... no, not as caroundw5h originally stated. It all depends on your definition of "incremented", imho. In the original sentence, caroundw5h said that (*p)++ and array[n]+1 did the same thing, when they don't. I think it's important to make that distinction at this stage At least, that's the way I read it.

    >>we really can't assume what else...
    Sure we can, it was in the middle of a descriptive example, attempting to show two ways to increment an int.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  13. #13
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >It all depends on your definition of "incremented", imho.
    I'm going by the standard's description:
    After the result is obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate type is added to it.)

    ...

    The side effect of updating the stored value of the operand shall occur between the previous and next sequence point.
    This clearly makes a distinction between incrementing (adding 1) and saving the result. But I'm being overly pedantic.

    >I think it's important to make that distinction at this stage
    I think trying to mix pointer offsets with array indices when one isn't familiar enough with either is a bad idea to begin with.

    >Sure we can
    Yes, that's true. But I was dying to see what your response to that question would be.
    My best code is written with the delete key.

  14. #14
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>This clearly makes a distinction between incrementing (adding 1) and saving the result
    Yes it does, but that still doesn't help your argument for the array[n]+1 "increment", because the value of array[n] will never change in this construct, meaning the "updating the stored value of the operand" bit is not valid. The Standard says add one AND store that value in the original location. Therefore I come to the conclusion that this operation is not an increment, m'lud.

    >>trying to mix pointer offsets
    >>bad idea
    Agreed, we're probably confusing poor 'ol caroundw5h even more now

    >>dying to see what your response
    Hope it was worth the wait

    >>But I'm being overly pedantic.
    Is there any other way?
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  15. #15
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Thank you guys very much for answering. I appreaciate the critique prelude, and your responses, i've updated my reference acordingly.

    Quote Originally Posted by Hammer
    No. This increments:
    >>(*p)++
    this doesn't:
    >>array[n] + 1
    The later only adds 1 to array[n] and returns it in a temporary int, leaving array[n] unchanged. It would be an increment if you did this though:
    >>array[n] = array[n] + 1;
    I believe I understand exactly what your saying hammer. I'm obvoiously mixing pointer and array notation. If i truly want to change the value at array[n] to array[n+1] then i should be assigning it to that element ie array[n] = array[n] + 1. thats my mistake, as this is new for me, i'm still getting through it. as it stands, with my notation, it is analogous to
    Code:
    int c = 10;
     printf("%d",c + 1);
    this doesn't really change the value of c, merly uses the constant c and adds 1 to it, and returns the sum. though c is not really changed at its address, it can still be called and manipulated and will have the value 10. is that about right?

    In anycase I agree with you. If i'm manipulating pointers, then do that, and stop mixing notation.
    on the other hand guys - i mean guy and girl - are there any problems or reasons with mixing notation?


    Agreed, we're probably confusing poor 'ol caroundw5h even more now
    Actually it has a steep learning curve, but I like it, this is why i turned to C. I'm very much inclined to using pointer notation and understand the W5H of it all, so i can better use it. Its obvious an intergal part of C and a very powerful feature. To be honest, I like it a lot. geeky as it sounds, I find it exciting, espeacailly with the possibilites i haven't thought of yet.

    In the same token, as pointers are really how C deals with a lot - if not all - objects. if i code in pointer notation, is it trully faster than array notation or the syntax Ritchie abstracted for us to use. Or does it not make a difference?
    Last edited by caroundw5h; 07-06-2004 at 09:51 AM.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Variable pointers and function pointers
    By Luciferek in forum C++ Programming
    Replies: 11
    Last Post: 08-02-2008, 02:04 AM
  2. Using pointers to pointers
    By steve1_rm in forum C Programming
    Replies: 18
    Last Post: 05-29-2008, 05:59 AM
  3. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  4. Staticly Bound Member Function Pointers
    By Polymorphic OOP in forum C++ Programming
    Replies: 29
    Last Post: 11-28-2002, 01:18 PM