简体   繁体   中英

When subtracting two pointers in C

I was playing with pointers in order to fully get the concept and then wanted to subtract two pointers expecting the distance between these two addresses or something, but apparently I was wrong, so here is my code.

int x = 5, y = 7;
int *p = &y;
int *q = &x;
printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));

Why does the program output p - q is 1 ? Thank you.

It is undefined behavior. According to the standard ( N1570 ):

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.

Note that when allowed, the result is the subscripts difference. So if pointers point to two sequential elements of the same type, the subtraction gives 1 , regardless of the size of the type. (This is perhaps the reason why you get 1 in your concrete case.)

Your particular case is cause for undefined behavior since p and q point to unrelated objects.

You can make sense of pq only if p and q point to the same array/one past the last element of the same array.

int array[10];
int* p = &array[0];
int* q = &array[5];

int ptrdiff_t = q - p;  // Valid. diff1 is 5
int ptrdiff_t = p - q;  // Valid. diff2 is -5

q - p is 5 in this case since they point to elements of the array that are 5 elements apart.

Put another way, p+5 is equal to q . If you start from p and step over 5 elements of the array, you will point to the same element of the array that q points to.


As an aside, don't use the format specifier %d for printing pointers. Use %p . Use %td for ptrdiff_t .

printf(" p is %p\n q is %p\n p-q is :%td", p, q, p-q);`
//            ^^        ^^

See http://en.cppreference.com/w/c/io/fprintf for the valid format specifiers for the different types.

Pointer arithmetic works like that. It doesn't give you differences between two addresses. Instead it will show difference between two variables as if they are stored in an array. so, no matter if your variables (of same type ) are 4 bytes, 8 bytes or 1 byte, if stored in adjacent memory location their pointer subtraction will always result in 1 or -1.

The subtraction of 2 pointers give the distance in between the 2 variables. For eg.

//let the address of a is 1000 then of a+1 will be 1004

int a[]={1,2,3};
int *p1=a;
int *p2=a+1;
printf("%u",p2-p1);

The result of this will be 1 not 4. Same here in your case the the location of x and y are consecutive that is why the ans. is 1.

The formula used by pointer substraction is:

( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )

with T being the type of both p1 and p2 .

int array[10];
int* p1 = array + 2;
int* p2 = array + 5;

int* a = p2 - p1; // == 3
int* b = p1 - p2; // == -3 
int a=5,b=6;
int *ptr=&a,*diff;
diff=ptr;
printf("%p\n",diff);
ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;
printf("%p\n",ptr);

printf("diff==%td\n",(ptr-diff)*sizeof(int));

(diff-ptr) will provide the distance between two variables, but will not provide the memory gap between two pointers. Important: only the same type of pointer can be subtracted.

The subtraction of two pointers in array will give the distance between the two elements.

Let the address of first element ie, is 1000 then address of second element a+1 will be 1004. Hence p1 = 1000 and p2 =1004 .

p2-p1 = (1004- 1000) /size of int = (1004-1000)/4 =4/4 =1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM