Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Pointer difficulties (http://www.velocityreviews.com/forums/t669167-pointer-difficulties.html)

 spasmous 02-06-2009 07:58 AM

Pointer difficulties

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

}

 user923005 02-06-2009 08:22 AM

Re: Pointer difficulties

On Feb 5, 11:58*pm, spasmous <spasm...@gmail.com> 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.

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.

 spasmous 02-06-2009 08:28 AM

Re: Pointer difficulties

On Feb 6, 12:22*am, user923005 <dcor...@connx.com> wrote:
> On Feb 5, 11:58*pm, spasmous <spasm...@gmail.com> 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 ;)

 Martin Ambuhl 02-06-2009 09:41 AM

Re: Pointer difficulties

spasmous wrote:
> On Feb 6, 12:22 am, user923005 <dcor...@connx.com> 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.

 Ike Naar 02-06-2009 10:41 AM

Re: Pointer difficulties

spasmous <spasmous@gmail.com> 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

 spasmous 02-06-2009 04:38 PM

Re: Pointer difficulties

On Feb 6, 1:41*am, Martin Ambuhl <mamb...@earthlink.net> wrote:
> spasmouswrote:
> > On Feb 6, 12:22 am, user923005 <dcor...@connx.com> 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 02-06-2009 04:39 PM

Re: Pointer difficulties

On Feb 6, 4:48*am, Han from China <autistic-pedan...@comp.lang.c>
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 :)

 John Bode 02-06-2009 07:43 PM

Re: Pointer difficulties

On Feb 6, 1:58*am, spasmous <spasm...@gmail.com> 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?

 Default User 02-06-2009 10:03 PM

Re: Pointer difficulties

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

 CBFalconer 02-07-2009 02:40 AM

Re: Pointer difficulties

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>