Pointer difficulties

S

spasmous

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

}
 
U

user923005

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

spasmous

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 ;)
 
M

Martin Ambuhl

spasmous said:
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.
 
I

Ike Naar

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
 
S

spasmous

spasmouswrote:


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

spasmous

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 :)
 
J

John Bode

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

CBFalconer

spasmous said:
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.
 
R

Richard

CBFalconer said:
spasmous said:
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.
 
K

Kaz Kylheku

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

Kaz Kylheku

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]!
 
I

Ike Naar

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top