Re: Pointer difficulties
- From: Han from China <autistic-pedantry@xxxxxxxxxxx>
- Date: Fri, 6 Feb 2009 05:48:00 -0700 (MST)
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);
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;
}
$ gcc -DVERS1 -o code code.c
$ ./code
1.000000 0.000000
1 2 3 4 5 42
6 7 8 9 0 42
1.000000 6.000000
1 2 3 4 5 42
6 7 8 9 0 42
1.000000 6.000000
1 2 3 4 5 42
6 7 8 9 0 42
1.000000 6.000000
1 2 3 4 5 42
6 7 8 9 0 42
2.000000 6.000000
1 2 3 4 5 42
6 7 8 9 0 42
2.000000 7.000000
1 2 3 4 5 42
6 7 8 9 0 42
2.000000 7.000000
1 2 3 4 5 42
6 7 8 9 0 42
2.000000 7.000000
1 2 3 4 5 42
6 7 8 9 0 42
3.000000 7.000000
1 2 3 4 5 42
6 7 8 9 0 42
3.000000 8.000000
1 2 3 4 5 42
6 7 8 9 0 42
3.000000 8.000000
1 2 3 4 5 42
6 7 8 9 0 42
3.000000 8.000000
1 2 3 4 5 42
6 7 8 9 0 42
4.000000 8.000000
1 2 3 4 5 42
6 7 8 9 0 42
4.000000 9.000000
1 2 3 4 5 42
6 7 8 9 0 42
4.000000 9.000000
1 2 3 4 5 42
6 7 8 9 0 42
4.000000 9.000000
1 2 3 4 5 42
6 7 8 9 0 42
5.000000 9.000000
1 2 3 4 5 42
6 7 8 9 0 42
5.000000 0.000000
1 2 3 4 5 42
6 7 8 9 0 42
5.000000 0.000000
1 2 3 4 5 42
6 7 8 9 0 42
5.000000 0.000000
1 2 3 4 5 42
6 7 8 9 0 42
$ gcc -o code code.c
$ ./code
1.000000 0.000000
1 2 3 4 5 42
6 7 8 9 0 42
1.000000 6.000000
1 2 3 4 5 42
6 7 8 9 0 42
1.000000 6.000000
1 1 3 4 5 42
6 7 8 9 0 42
1.000000 6.000000
1 1 3 4 5 42
6 6 8 9 0 42
1.000000 6.000000
1 1 3 4 5 42
6 6 8 9 0 42
1.000000 6.000000
1 1 3 4 5 42
6 6 8 9 0 42
1.000000 6.000000
1 1 1 4 5 42
6 6 8 9 0 42
1.000000 6.000000
1 1 1 4 5 42
6 6 6 9 0 42
1.000000 6.000000
1 1 1 4 5 42
6 6 6 9 0 42
1.000000 6.000000
1 1 1 4 5 42
6 6 6 9 0 42
1.000000 6.000000
1 1 1 1 5 42
6 6 6 9 0 42
1.000000 6.000000
1 1 1 1 5 42
6 6 6 6 0 42
1.000000 6.000000
1 1 1 1 5 42
6 6 6 6 0 42
1.000000 6.000000
1 1 1 1 5 42
6 6 6 6 0 42
1.000000 6.000000
1 1 1 1 1 42
6 6 6 6 0 42
1.000000 6.000000
1 1 1 1 1 42
6 6 6 6 6 42
1.000000 6.000000
1 1 1 1 1 42
6 6 6 6 6 42
1.000000 6.000000
1 1 1 1 1 42
6 6 6 6 6 42
1.000000 6.000000
1 1 1 1 1 1
6 6 6 6 6 42
1.000000 6.000000
1 1 1 1 1 1
6 6 6 6 6 6
Yours,
Han from China
--
"Only entropy comes easy." -- Anton Chekhov
.
- Follow-Ups:
- Re: Pointer difficulties
- From: Kaz Kylheku
- Re: Pointer difficulties
- From: spasmous
- Re: Pointer difficulties
- References:
- Pointer difficulties
- From: spasmous
- Pointer difficulties
- Prev by Date: Re: language extensions needed by linux /usr/include headers
- Next by Date: Re: how does printf handle an unknown number of arguments
- Previous by thread: Re: Pointer difficulties
- Next by thread: Re: Pointer difficulties
- Index(es):
Relevant Pages
|