3

Is subtraction of pointers not pointing to different elements of same array valid in C?

Is something such as below guaranteed to work according to C Standards? I vaguely remember reading that this is not valid?

int * a;
int * b;
a = (int*) 100;
b = (int*) 200;
printf("%d\n", b-a);

Will this give me 25.

sidyll
  • 57,726
  • 14
  • 108
  • 151
disputedbug
  • 265
  • 1
  • 3
  • 6
  • 1
    Technically, even assigning random ints to a pointer isn't valid standard C in the first place. – Random832 Mar 12 '12 at 18:57
  • Even if it were defined, pointer subtraction yields a result of type `ptrdiff_t`, and `"%d"` requires an `int` argument. The last line should be something like `printf("%d\n", (int)(b-a));`. – Keith Thompson Mar 12 '12 at 19:02
  • 1
    @Random832: Depends on what you mean by "valid". It's not undefined behavior. [N1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 6.3.2.3p5: "An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation." But it's very likely to be nonsense. – Keith Thompson Mar 12 '12 at 19:04
  • @KeithThompson Thanks. Looking at your control on C, I must ask, are you related to Ken Thompson? Just kidding. – disputedbug Mar 12 '12 at 19:11
  • @disputedbug: No, but I was once mistaken for him. – Keith Thompson Mar 12 '12 at 19:15
  • @KeithThompson: Actually that would be `printf("%td\n", b - a);`. – mk12 Aug 23 '12 at 20:18
  • @Mk12: Right (assuming your implementation supports it). – Keith Thompson Aug 23 '12 at 23:20

4 Answers4

6

From the C spec, Appendix J.2 Undefined behaviour:

Pointers that do not point into, or just beyond, the same array object are subtracted (6.5.6).

6.5.6 Additive operators, paragraph 9 says:

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements.

There you have it - your example causes undefined behaviour. That said, on most systems it will work just fine. You probably do want to change your printf format to %td to indicate that you're printing a ptrdiff_t type.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
4

This is undefined behavior.

For one, those pointers don't point to memory that you own.

You can only substract pointers that point inside the same array (or one position after the end of the array).

Of course, it will most likely work on most compilers, and you get 25 because sizeof(int) == 4 on your platform. If they were char *, you'd get 100. (possibly, or it could crash, that's the beauty of UB).

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

Even the standard does not promise a defined behavior, the result is correct. An integer needs in your architecture 4 bytes. Thus, the difference give you the number of integer values the both pointer are apart. You can use the difference as an index or offset in an array. For the same reason

  int *p = (int*) 100;
  p++;

will result in p=104.

Matthias
  • 8,018
  • 2
  • 27
  • 53
0

Of course it's undefined. Subtracting two arbitrary pointers (viewed as integers) is not even guaranteed to be a multiple of your object's size.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243