Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does pointer subtraction in C yield an integer?

Tags:

c

pointers

Why if I subtract from a pointer another pointer (integer pointers) without typecasting the result will be 1 and not 4 bytes (like it is when I typecast to int both pointers). Example :

int a , b , *p , *q;
p = &b;
q = p + 1; // q = &a;
printf("%d",q - p); // The result will be one .
printf("%d",(int)q - (int)p); // The result will be 4(bytes). The memory address of b minus The memory address of a.
like image 316
Călin Calin Avatar asked Jan 22 '16 20:01

Călin Calin


3 Answers

According to the C Standard (6.5.6 Additive operators)

9 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....

If the two pointers pointed to elements of the same array then as it is said in the quote from the Standard

the result is the difference of the subscripts of the two array elements

That is you would get the number of elements of the array between these two pointers. It is the result of the so-called pointer arithmetic.

If you subtract addresses stored in the pointers as integer values then you will get the number that corresponds to the arithmetic subtract operation.

like image 192
Vlad from Moscow Avatar answered Sep 18 '22 22:09

Vlad from Moscow


Why If If I subtract from a pointer another pointer (integer pointers) without typecasting the result will be 1 and not 4 bytes

That's the whole point of the data type that a pointer pointing to. It's probably easier to look at an array context like below. The point is regardless of the underlying data type (here long or double), you can use pointer arithmetic to navigate the array without caring about how exactly the size of its element is. In other words, (pointer + 1) means point the next element regardless of the type.

long l[] = { 10e4, 10e5, 10e6 };
long *pl = l + 1;    // point to the 2nd element in the "long" array.

double d[] = { 10e7, 10e8, 10e9 };
double *pd = d + 2;    // point to the 3rd element in the "double" array.

Also note in your code:

int a , b , *p , *q;
p = &b;
q = p + 1; // q = &a;   <--- NO this is wrong. 

The fact that a and b are declared next to each other does not mean that a and b are allocated next to each other in the memory. So q is pointing to the memory address next to that of b - but what is in that address is undefined.

like image 41
artm Avatar answered Sep 20 '22 22:09

artm


Because the ptrdiff_t from pointer subtraction is calculated relative to the size of the elements pointed to. It's a lot more convenient that way; for one, it tells you how many times you can increment one pointer before you reach the other pointer.

like image 34
ShadowRanger Avatar answered Sep 18 '22 22:09

ShadowRanger