jmcgill said:
Saw this used as an example. Compiles without warnings. "Works."
Kosher or not?
Why or why not?
#include <stdio.h>
int main(int argc, char **argv){
int i,j,k,l,m;
int *p;
i=2; j=4; k=8; l=32; m=64; /*any values*/
p = &i;
*p = *p+1;
*(p+1) = *(p+1) +1;
*(p+2) = *(p+2) -1;
printf("{i,j,k,l,m}={%d,%d,%d,%d,%d}\n", i,j,k,l,m);
return 0;
}
I sympathise with your motivation for asking, and of course it's obvious
that it isn't kosher. It isn't even halal. Here's the output on my system:
{i,j,k,l,m}={3,4,8,32,64}
Segmentation fault (core dumped)
Let's now investigate why the program is incorrect.
#include <stdio.h>
int main(int argc, char **argv){
argc and argv are not used, but apart from that we're looking good so far.
int i,j,k,l,m;
int *p;
Well, okay.
i=2; j=4; k=8; l=32; m=64; /*any values*/
Still legal.
p = &i;
p points to i. So *p has the value 2.
*p = *p+1;
*p (i.e. i) now has the value 3.
*(p+1) = *(p+1) +1;
It is legal to form the pointer p + 1, since i can be considered "as if" it
were an array of one int, and it is legal to point one past the end of an
array. It is not, however, legal to dereference that pointer, which this
code does. Chapter and verse is in:
3.3.6 Additive operators:
[...] When an expression that has integral type is added to or subtracted
from a pointer, the integral value is first multiplied by the size of the
object pointed to. The result has the type of the pointer operand. If the
pointer operand points to a member of an array object, and the array object
is large enough, the result points to a member of the same array object,
appropriately offset from the original member. Thus if P points to a
member of an array object, the expression P+1 points to the next member of
the array object. Unless both the pointer operand and the result point to
a member of the same array object, or one past the last member of the array
object, the behavior is undefined.
So whoever wrote the program needs to learn C before they try teaching it.