Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subtraction between pointers of different type [duplicate]

I'm trying to find the distance in memory between two variables. Specifically I need to find the distance between a char[] array and an int.

    char data[5];
    int a = 0;

    printf("%p\n%p\n", &data[5], &a);

    long int distance = &a - &data[5];

    printf("%ld\n", distance);

When I run my my program without the last two lines I get the proper memory address of the two variables, something like this:

   0x7fff5661aac7
   0x7fff5661aacc

Now I understand, if I'm not wrong, that there are 5 bytes of distance between the two (0x7fff5661aac8, 0x7fff5661aac9, 0x7fff5661aaca, 0x7fff5661aacb, 0x7fff5661aacc).

Why I can't subtract a pointer of type (int *) and one of type (char *). Both refer to memory address.. What should I do in order to calculate the distance, in bytes, between the two?? I tried casting one of the two pointers but it's not working.

I get: "error: 'char *' and 'int *' are not pointers to compatible types". Thanks to everyone will help me

like image 661
fedemengo Avatar asked Dec 08 '22 20:12

fedemengo


2 Answers

Nopes, this is not possible.

First, you can only subtract pointers of (to) "compatible" types, an int and a char are not compatible types here. Hence the subtraction is not possible.

That said, even if both are pointers to compatible type, then also, the following comes into picture.

So, secondly You cannot just subtract two arbitrary pointers, they need to be essentially part of (address for elements of) the same array. Othweise, it invokes undefined behavior.

Quoting C11, chapter §6.5.6, Additive operators

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. [....]

Thirdly, another important point, the result of subtraction of two pointers is of type ptrdiff_t, a signed integer type.

[...] The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. [...]

so, to print the result, you need to use %td format specifier.

like image 160
Sourav Ghosh Avatar answered Dec 10 '22 10:12

Sourav Ghosh


Pointer subtraction is only defined for pointers within the same array (or just past the last element of an array). Any other use is undefined behavior. Let's ignore that for your experimentation.

When two pointers of the same type to elements of the same array object are subtracted, the result is the difference of the array indices. You could add that signed integer result (of type ptrdiff_t) to the first pointer and get the value of the second pointer, or subtract the result from the second pointer and get the value of the first pointer. So in effect, the result is the difference in the byte address of the two pointers divided by the size of the object being pointed to. This is why it makes no sense to allow subtraction of pointers of incompatible type, particularly when the referenced object types are of different size. How could you divide the difference in byte address by the size of the object being pointed to when the pointers being subtractedare referring to differently sized objects?

Still, for experimentation purposes, you can cast both pointers (pointing to different objects) to char * and subtract them, and many compilers will just give you the difference in their byte address as a number. However, the result could overflow an integer of ptrdiff_t. Alternatively, you can convert both pointers to an integer of type intptr_t and subtract the integers to get the difference in byte address. Again, it's theoretically possible that the result of the subtraction could overflow an integer of type intptr_t.

like image 20
Ian Abbott Avatar answered Dec 10 '22 10:12

Ian Abbott