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