Pointer difficulties

Discussion in 'C Programming' started by spasmous, Feb 6, 2009.

  1. spasmous

    spasmous Guest

    Below are two versions of code that I expected to do the same thing.
    However they don't. I'm having difficulty seeing what is causing the
    different behaviour - can someone please explain it to me! Thank you!!

    int n = 10,m=100;
    double y[n];
    short *p[n]; // pointers to arrays of length m

    // this gives the desired result
    for(int j=0; j<m; j++) {

    for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    do_stuff(y);
    *(p[0]+j) = (short)y[0];
    *(p[1]+j) = (short)y[1];

    }

    // this does not give the desired result
    for(int j=0; j<m; j++) {

    for(int k=0; k<n; k++) y[k] = *(p[k]++);
    do_stuff(y);
    *(p[0]) = (short)y[0];
    *(p[1]) = (short)y[1];

    }
     
    spasmous, Feb 6, 2009
    #1
    1. Advertising

  2. spasmous

    user923005 Guest

    On Feb 5, 11:58 pm, spasmous <> wrote:
    > Below are two versions of code that I expected to do the same thing.
    > However they don't. I'm having difficulty seeing what is causing the
    > different behaviour - can someone please explain it to me! Thank you!!
    >
    > int n = 10,m=100;
    > double y[n];
    > short *p[n]; // An array of ten pointers to short, initialize to NULL
    >
    > // this gives the desired result
    > for(int j=0; j<m; j++) {
    >
    >     for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    >     do_stuff(y);
    >     *(p[0]+j) = (short)y[0];
    >     *(p[1]+j) = (short)y[1];
    >
    > }
    >
    > // this does not give the desired result
    > for(int j=0; j<m; j++) {
    >
    >     for(int k=0; k<n; k++) y[k] = *(p[k]++);
    >     do_stuff(y);
    >     *(p[0]) = (short)y[0];
    >     *(p[1]) = (short)y[1];
    >
    >
    >
    > }


    Neither one is going to do something sensible.

    This will compile, but exhibits undefined behavior on first access to
    a NULL pointer.

    #define n 10
    #define m 100
    double y[n];
    short *p[n]; /* 10 null pointers to short */

    void do_stuff(double *y)
    {
    return;
    }

    int main(void)
    {
    int j,k;
    /* this supposedly gives the desired result */
    for (j = 0; j < m; j++) {
    for (k = 0; k < n; k++)
    y[k] = *(p[k] + j);
    do_stuff(y);
    *(p[0] + j) = (short) y[0];
    *(p[1] + j) = (short) y[1];
    }

    /* this does not give the desired result (no surprise there) */
    for (j = 0; j < m; j++) {
    for (k = 0; k < n; k++)
    y[k] = *(p[k]++);
    do_stuff(y);
    *(p[0]) = (short) y[0];
    *(p[1]) = (short) y[1];
    }
    return 0;
    }

    I guess that your post is a troll.
     
    user923005, Feb 6, 2009
    #2
    1. Advertising

  3. spasmous

    spasmous Guest

    On Feb 6, 12:22 am, user923005 <> wrote:
    > On Feb 5, 11:58 pm, spasmous <> wrote:
    >
    >
    >
    > > Below are two versions of code that I expected to do the same thing.
    > > However they don't. I'm having difficulty seeing what is causing the
    > > different behaviour - can someone please explain it to me! Thank you!!

    >
    > > int n = 10,m=100;
    > > double y[n];
    > > short *p[n]; // An array of ten pointers to short, initialize to NULL

    >
    > > // this gives the desired result
    > > for(int j=0; j<m; j++) {

    >
    > >     for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    > >     do_stuff(y);
    > >     *(p[0]+j) = (short)y[0];
    > >     *(p[1]+j) = (short)y[1];

    >
    > > }

    >
    > > // this does not give the desired result
    > > for(int j=0; j<m; j++) {

    >
    > >     for(int k=0; k<n; k++) y[k] = *(p[k]++);
    > >     do_stuff(y);
    > >     *(p[0]) = (short)y[0];
    > >     *(p[1]) = (short)y[1];

    >
    > > }

    >
    > Neither one is going to do something sensible.
    >
    > This will compile, but exhibits undefined behavior on first access to
    > a NULL pointer.
    >
    > #define  n  10
    > #define  m  100
    > double          y[n];
    > short          *p[n];  /* 10 null pointers to short */
    >
    > void do_stuff(double *y)
    > {
    >         return;
    >
    > }
    >
    > int             main(void)
    > {
    >         int j,k;
    > /* this supposedly gives the desired result */
    >     for (j = 0; j < m; j++) {
    >         for (k = 0; k < n; k++)
    >             y[k] = *(p[k] + j);
    >         do_stuff(y);
    >         *(p[0] + j) = (short) y[0];
    >         *(p[1] + j) = (short) y[1];
    >     }
    >
    > /* this does not give the desired result (no surprise there) */
    >     for (j = 0; j < m; j++) {
    >         for (k = 0; k < n; k++)
    >             y[k] = *(p[k]++);
    >         do_stuff(y);
    >         *(p[0]) = (short) y[0];
    >         *(p[1]) = (short) y[1];
    >     }
    >     return 0;
    >
    > }
    >
    > I guess that your post is a troll.


    lol hardly. Take a huge leap and imagine p getting initialized without
    it being spelt out for you ;)
     
    spasmous, Feb 6, 2009
    #3
  4. spasmous wrote:
    > On Feb 6, 12:22 am, user923005 <> wrote:

    [..]
    >> I guess that your post is a troll.

    >
    > lol hardly. Take a huge leap and imagine p getting initialized without
    > it being spelt out for you ;)


    Take a huge leap and post real code. When you have problems and leave
    out part of the relevant code, the best possible guess is that the part
    you left out doesn't exist and that part of your problem lies there.

    Unlike Mr. Corbit, I did not take your initial post as a troll. You
    snotty and frankly stupid response to him does suggest that he was right.
     
    Martin Ambuhl, Feb 6, 2009
    #4
  5. spasmous

    Ike Naar Guest

    In article <>,
    spasmous <> wrote:
    >Below are two versions of code that I expected to do the same thing.
    >However they don't. I'm having difficulty seeing what is causing the
    >different behaviour - can someone please explain it to me! Thank you!!
    >
    >int n = 10,m=100;
    >double y[n];
    >short *p[n]; // pointers to arrays of length m
    >
    >// this gives the desired result
    >for(int j=0; j<m; j++) {
    > for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    > do_stuff(y);
    > *(p[0]+j) = (short)y[0];
    > *(p[1]+j) = (short)y[1];
    >}
    >
    >// this does not give the desired result
    >for(int j=0; j<m; j++) {
    > for(int k=0; k<n; k++) y[k] = *(p[k]++);
    > do_stuff(y);
    > *(p[0]) = (short)y[0];
    > *(p[1]) = (short)y[1];
    >}


    In the second variant, you increment p[k], for every k in 0..n-1,
    at the start of the body; that means that at the end of the body
    p[0] and p[1] alreay have been incremented, so the assignment

    *(p[0]) = (short)y[0];

    does not do the same thing as the corresponding assignment in the
    first variant. Look what happens if you change the assigment to:

    *(p[0]-1) = (short)y[0];

    Regards,
    Ike
     
    Ike Naar, Feb 6, 2009
    #5
  6. spasmous

    spasmous Guest

    On Feb 6, 1:41 am, Martin Ambuhl <> wrote:
    > spasmouswrote:
    > > On Feb 6, 12:22 am, user923005 <> wrote:

    > [..]
    > >> I guess that your post is a troll.

    >
    > > lol hardly. Take a huge leap and imagine p getting initialized without
    > > it being spelt out for you ;)

    >
    > Take a huge leap and post real code.  When you have problems and leave
    > out part of the relevant code, the best possible guess is that the part
    > you left out doesn't exist and that part of your problem lies there.
    >
    > Unlike Mr. Corbit, I did not take your initial post as a troll.  You
    > snotty and frankly stupid response to him does suggest that he was right.


    lol this is hilarious, real passion!! anyway, thanks I won't need your
    "best possible guess" this time (which was also wrong). he he, arguin
    on the internets...
     
    spasmous, Feb 6, 2009
    #6
  7. spasmous

    spasmous Guest

    On Feb 6, 4:48 am, Han from China <>
    wrote:
    > spasmouswrote:
    > > Below are two versions of code that I expected to do the same thing.
    > > However they don't. I'm having difficulty seeing what is causing the
    > > different behaviour - can someone please explain it to me! Thank you!!

    >
    > > int n = 10,m=100;
    > > double y[n];
    > > short *p[n]; // pointers to arrays of length m

    >
    > > // this gives the desired result
    > > for(int j=0; j<m; j++) {

    >
    > >    for(int k=0; k<n; k++) y[k] = *(p[k]+j);

    >
    > Each iteration of the top loop results in populating y[] with the j'th column
    > of a 10x100 matrix.
    >
    > >    do_stuff(y);
    > >    *(p[0]+j) = (short)y[0];
    > >    *(p[1]+j) = (short)y[1];

    >
    > Elements 0,j and 1,j of the 10x100 matrix are altered. This doesn't affect
    > the next iteration, since the j'th column has already been used.
    >
    > > }

    >
    > > // this does not give the desired result
    > > for(int j=0; j<m; j++) {

    >
    > >    for(int k=0; k<n; k++) y[k] = *(p[k]++);

    >
    > Each iteration of the top loop results in populating y[] with the j'th column
    > of a 10x100 matrix. Same as in the first version.
    >
    > >    do_stuff(y);
    > >    *(p[0]) = (short)y[0];
    > >    *(p[1]) = (short)y[1];

    >
    > Elements 0,(j+1) and 1,(j+1) of the 10x100 matrix are altered. This affects
    > the next iteration, since the (j+1)'th column has not already been used.
    > The program has undefined behavior because the final iteration results in
    > two stores to an "element" one past the final element of an array. Note that the
    > *(p[k]++); which gets there is fine, since you're allowed to store the
    > address of the "element" one past the final element of an array, but you're
    > not allowed to access the "element" there for either a read or a write, and
    > you write there with the final stores to *(p[0]) and *(p[1]).
    >
    > > }

    >
    > I have modified your code to use a 2x5 matrix, to make do_stuff() a no-op,
    > and to print some debugging output. I have used a virtual 6th column
    > initialized with the value of 42 to show the overwrite in the final
    > iteration of your second code version.
    >
    > #include <stdio.h>
    >
    > int n = 2, m = 5;
    > double y[2];
    > short array1[] = {1, 2, 3, 4, 5, 42};
    > short array2[] = {6, 7, 8, 9, 0, 42};
    > short *p[2] = {array1, array2}; // pointers to arrays of length m
    >
    > void showit(void)
    > {
    >    printf("%f %f\n", y[0], y[1]);
    >
    >    printf("%d %d %d %d %d %d\n",
    >          array1[0], array1[1], array1[2], array1[3], array1[4], array1[5]);
    >
    >    printf("%d %d %d %d %d %d\n",
    >          array2[0], array2[1], array2[2], array2[3], array2[4], array2[5]);
    >
    > }
    >
    > int main(void)
    > {
    > int j, k;
    > #ifdef VERS1
    > // this gives the desired result
    > for(j=0; j<m; j++) {
    >
    >     for(k=0; k<n; k++) y[k] = *(p[k]+j), showit();
    >     //do_stuff(y);
    >     *(p[0]+j) = (short)y[0], showit();
    >     *(p[1]+j) = (short)y[1], showit();
    >
    > }
    >
    > #else
    > // this does not give the desired result
    > for(j=0; j<m; j++) {
    >
    >     for(k=0; k<n; k++) y[k] = *(p[k]++), showit();
    >     //do_stuff(y);
    >     *(p[0]) = (short)y[0], showit();
    >     *(p[1]) = (short)y[1], showit();}
    >
    > #endif
    >
    >   return 0;
    >
    > }



    Han and Ike, thank you so much. Of course it's obvious now :)
     
    spasmous, Feb 6, 2009
    #7
  8. spasmous

    John Bode Guest

    On Feb 6, 1:58 am, spasmous <> wrote:
    > Below are two versions of code that I expected to do the same thing.
    > However they don't. I'm having difficulty seeing what is causing the
    > different behaviour - can someone please explain it to me! Thank you!!
    >
    > int n = 10,m=100;
    > double y[n];
    > short *p[n]; // pointers to arrays of length m
    >


    I'm assuming the elements in p are assigned before the following code
    executes, otherwise bad things happen. Basically, p is treated as a
    10x100 array of short, right?

    > // this gives the desired result
    > for(int j=0; j<m; j++) {
    >
    >     for(int k=0; k<n; k++) y[k] = *(p[k]+j);


    You can use a subscript operator on a pointer if you're treating the
    pointer as an array; IOW, you could write p[k][j] as opposed to *(p[k]
    +j). That might clarify things.

    Are you assigning shorts to doubles by design?

    >     do_stuff(y);
    >     *(p[0]+j) = (short)y[0];
    >     *(p[1]+j) = (short)y[1];


    Basically, you're doing

    p[0][0] = y[0]; // j = 0
    p[1][0] = y[1];
    p[0][1] = y[0]; // j = 1
    p[1][1] = y[1];
    p[0][2] = y[0]; // j = 2
    p[1][2] = y[1];
    ...

    etc. Is that the intent?

    >
    > }
    >
    > // this does not give the desired result
    > for(int j=0; j<m; j++) {
    >
    >     for(int k=0; k<n; k++) y[k] = *(p[k]++);
    >     do_stuff(y);
    >     *(p[0]) = (short)y[0];
    >     *(p[1]) = (short)y[1];
    >


    That expands to

    p[0][0] = y[0];
    p[1][0] = y[1];
    p[0][0] = y[0];
    p[1][0] = y[1];
    ...

    etc.
    >
    >
    > }- Hide quoted text -
    >
    > - Show quoted text -


    What exactly *is* the desired result?
     
    John Bode, Feb 6, 2009
    #8
  9. spasmous

    Default User Guest

    spasmous wrote:

    > he he, arguin on the internets...


    Historically, that has been one of its prime functions.




    Brian

    --
    Day 3 of the "no grouchy usenet posts" project
     
    Default User, Feb 6, 2009
    #9
  10. spasmous

    CBFalconer Guest

    spasmous wrote:
    >
    > Below are two versions of code that I expected to do the same
    > thing. However they don't. I'm having difficulty seeing what is
    > causing the different behaviour - can someone please explain it
    > to me! Thank you!!
    >
    > int n = 10,m=100;
    > double y[n];
    > short *p[n]; // pointers to arrays of length m
    >
    > // this gives the desired result
    > for(int j=0; j<m; j++) {
    > for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    > do_stuff(y); ^-- ** This is 0 thru 99
    > *(p[0]+j) = (short)y[0];
    > *(p[1]+j) = (short)y[1];
    > }
    >
    > // this does not give the desired result
    > for(int j=0; j<m; j++) {
    > for(int k=0; k<n; k++) y[k] = *(p[k]++);
    > do_stuff(y); ^-- ** This incr is 1
    > *(p[0]) = (short)y[0];
    > *(p[1]) = (short)y[1];
    > }


    See the '**' annotations above.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.
     
    CBFalconer, Feb 7, 2009
    #10
  11. spasmous

    Richard Guest

    CBFalconer <> writes:

    > spasmous wrote:
    >>
    >> Below are two versions of code that I expected to do the same
    >> thing. However they don't. I'm having difficulty seeing what is
    >> causing the different behaviour - can someone please explain it
    >> to me! Thank you!!
    >>
    >> int n = 10,m=100;
    >> double y[n];
    >> short *p[n]; // pointers to arrays of length m
    >>
    >> // this gives the desired result
    >> for(int j=0; j<m; j++) {
    >> for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    >> do_stuff(y); ^-- ** This is 0 thru 99


    So what?

    >> *(p[0]+j) = (short)y[0];
    >> *(p[1]+j) = (short)y[1];
    >> }
    >>
    >> // this does not give the desired result
    >> for(int j=0; j<m; j++) {
    >> for(int k=0; k<n; k++) y[k] = *(p[k]++);
    >> do_stuff(y); ^-- ** This incr is 1
    >> *(p[0]) = (short)y[0];
    >> *(p[1]) = (short)y[1];
    >> }

    >
    > See the '**' annotations above.


    Note to the OP : the code above is hard to read and hard to
    debug. Never, ever put the body of something like a for loop on the same
    line. It's hard to use a debugger on it for a start.

    for(int k=0; k<n; k++){
    y[k] = *(p[k]+j);
    }

    Is much more readable, easier to extend later and works in a debugger
    properly usually.

    If we look at the second loop:

    for(int k=0; k<n; k++){
    y[k] = *(p[k]++);
    }

    ... one has to ask what you expected. p[k] returns a value which then
    dereferenced. After that the value is post incremented but ignored
    (likely optimised out anyway).

    Since you dont express what the desired behaviour is once must wonder if
    you are sure the first does indeed produce it.
     
    Richard, Feb 7, 2009
    #11
  12. spasmous

    Kaz Kylheku Guest

    On 2009-02-06, spasmous <> wrote:
    > Below are two versions of code that I expected to do the same thing.
    > However they don't. I'm having difficulty seeing what is causing the
    > different behaviour - can someone please explain it to me! Thank you!!
    >
    > int n = 10,m=100;
    > double y[n];
    > short *p[n]; // pointers to arrays of length m
    >
    > // this gives the desired result > for(int j=0; j<m; j++) {
    >
    > for(int k=0; k<n; k++) y[k] = *(p[k]+j);
    > do_stuff(y);
    > *(p[0]+j) = (short)y[0];
    > *(p[1]+j) = (short)y[1];
    >
    > }
    >
    > // this does not give the desired result
    > for(int j=0; j<m; j++) {
    >
    > for(int k=0; k<n; k++) y[k] = *(p[k]++);
    > do_stuff(y);
    > *(p[0]) = (short)y[0];
    > *(p[1]) = (short)y[1];
    >
    > }


    In addition to the other comments, I recommend array notation over
    *(x + y). Watch:

    for(int j=0; j<m; j++) {
    for(int k=0; k<n; k++)
    y[k] = p[k][j];
    do_stuff(y);
    p[0][j] = y[0];
    p[1][j] = y[1];
    }

    for(int j=0; j<m; j++) {
    for(int k=0; k<n; k++)
    y[k] = p[k]++[j];
    do_stuff(y);
    p[0][-1] = y[0];
    p[1][-1] = y[1];
    }

    Look, Ma, no *(p[0]+j) and *(p[k]++) obfuscation.
     
    Kaz Kylheku, Feb 7, 2009
    #12
  13. spasmous

    Kaz Kylheku Guest

    On 2009-02-06, Han from China <> wrote:
    > for(k=0; k<n; k++) y[k] = *(p[k]+j), showit();
    > //do_stuff(y);
    > *(p[0]+j) = (short)y[0], showit();
    > *(p[1]+j) = (short)y[1], showit();


    Oh yeah, /don't/ show the poor noob the secret of *(p[k]+j) being p[k][j]!
     
    Kaz Kylheku, Feb 7, 2009
    #13
  14. spasmous

    Ike Naar Guest

    In article <gmj8jj$2da$>,
    Richard <> wrote:
    >Note to the OP : the code above is hard to read and hard to debug.


    Looks like code from the "real world" ;-)

    >Never, ever put the body of something like a for loop on the same line.


    That is not what makes the code difficult to understand.

    >It's hard to use a debugger on it for a start.


    Solving (see elsethread) this particular problem through code reading
    turned out to be easier than trying to solve it with a debugger.

    >for(int k=0; k<n; k++){
    > y[k] = *(p[k]++);
    >}
    >
    >.. one has to ask what you expected. p[k] returns a value which then
    >dereferenced. After that the value is post incremented but ignored
    >(likely optimised out anyway).


    The incremented value is used in the next iteration of the main loop.
    For k=0,1 the value is used later in the same iteration as well.
     
    Ike Naar, Feb 7, 2009
    #14
    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. Philip Townsend

    Caching difficulties (control level)

    Philip Townsend, Aug 4, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    335
    Philip Townsend
    Aug 4, 2003
  2. Philip Townsend

    Repeater Difficulties

    Philip Townsend, Jan 9, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    370
    Michael
    Jan 9, 2004
  3. sonic
    Replies:
    3
    Views:
    502
    sonic
    Jan 12, 2005
  4. sonic
    Replies:
    0
    Views:
    304
    sonic
    Jan 12, 2005
  5. Dave
    Replies:
    0
    Views:
    411
Loading...

Share This Page