Velocity Reviews > Pointer difficulties

# Pointer difficulties

spasmous
Guest
Posts: n/a

 02-06-2009
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
Guest
Posts: n/a

 02-06-2009
On Feb 5, 11:58*pm, spasmous <(E-Mail Removed)> 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
Guest
Posts: n/a

 02-06-2009
On Feb 6, 12:22*am, user923005 <(E-Mail Removed)> wrote:
> On Feb 5, 11:58*pm, spasmous <(E-Mail Removed)> 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
Guest
Posts: n/a

 02-06-2009
spasmous wrote:
> On Feb 6, 12:22 am, user923005 <(E-Mail Removed)> 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
Guest
Posts: n/a

 02-06-2009
In article <(E-Mail Removed)>,
spasmous <(E-Mail Removed)> 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
Guest
Posts: n/a

 02-06-2009
On Feb 6, 1:41*am, Martin Ambuhl <(E-Mail Removed)> wrote:
> spasmouswrote:
> > On Feb 6, 12:22 am, user923005 <(E-Mail Removed)> 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
Guest
Posts: n/a

 02-06-2009
On Feb 6, 4:48*am, Han from China <(E-Mail Removed)>
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
Guest
Posts: n/a

 02-06-2009
On Feb 6, 1:58*am, spasmous <(E-Mail Removed)> 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
Guest
Posts: n/a

 02-06-2009
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
Guest
Posts: n/a

 02-07-2009
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>