|
| 1 | +#include <stdio.h> |
| 2 | + |
| 3 | +int main() { |
| 4 | + /* |
| 5 | + K&R say (p. 102, 2nd ed): |
| 6 | + "...pointers may be compared under certain circumstances. If p and q point to |
| 7 | + members of the same array, then relations like ==, 1=, <, >=, etc., work |
| 8 | + properly. For example, p < q is true if p points to an earlier member of the |
| 9 | + array than q does. Any pointer can be meaningfully compared for equality or |
| 10 | + inequality with zero. But the behavior is undefined for arithmetic or |
| 11 | + comparisons with pointers that do not point to members of the same array." |
| 12 | +
|
| 13 | + Let's confirm that! |
| 14 | + */ |
| 15 | + |
| 16 | + long array1[5] = {0, 1, 2, 3, 4}; |
| 17 | + long array2[3] = {5, 6, 7}; |
| 18 | + |
| 19 | + long *ip1, *ip2; |
| 20 | + |
| 21 | + // < is legal because the array is a contiguous block of bytes |
| 22 | + ip1 = &array1[0]; |
| 23 | + ip2 = &array1[1]; |
| 24 | + printf("ip1, ip2: %p, %p\n", (void *)ip1, (void *)ip2); |
| 25 | + printf("*ip1, *ip2: %ld, %ld\n", *ip1, *ip2); |
| 26 | + printf("ip1 < ip2: %d\n", ip1 < ip2); |
| 27 | + |
| 28 | + // < is undefined; we don't know where each thing is on the stack, and as |
| 29 | + // such, we can't assume that array1 is above or below array2 address-wise. |
| 30 | + ip2 = &array2[1]; |
| 31 | + printf("ip1, ip2: %p, %p\n", (void *)ip1, (void *)ip2); |
| 32 | + printf("*ip1, *ip2: %ld, %ld\n", *ip1, *ip2); |
| 33 | + printf("ip1 < ip2: %d\n", ip1 < ip2); |
| 34 | + |
| 35 | + // if we subtract p1 from p2 below, do we get the number of elements in the |
| 36 | + // array? Yes, make sure to add 1 as the last offset can store a value. This |
| 37 | + // works regardless of types. |
| 38 | + ip1 = &array1[0]; |
| 39 | + ip2 = &array1[4]; |
| 40 | + printf("ip2 - ip1: %ld\n", ip2 - ip1 + 1); |
| 41 | + |
| 42 | + /* |
| 43 | + Conclusion: pointer arithmetic is consistent; see K&R p. 103, 2nd ed: |
| 44 | + "The valid pointer operations are assignment of pointers of the same type, |
| 45 | + adding or subtracting a pointer and an integer, subtracting or comparing two |
| 46 | + pointers to members of the same array, and assigning or comparing to zero. All |
| 47 | + other pointer arithmetic is illegal. It is not legal to add two pointers, or |
| 48 | + to multiply or divide or shift or mask them, or to add float or double to |
| 49 | + them, or even, except for void *, to assign a pointer of one type to a pointer |
| 50 | + of another type without a cast." |
| 51 | + */ |
| 52 | + return 0; |
| 53 | +} |
0 commit comments