Subtracting two pointers giving unexpected result

后端 未结 6 1195
灰色年华
灰色年华 2021-01-26 14:56
#include 

int main() {
    int *p = 100;
    int *q = 92;
    printf(\"%d\\n\", p - q);  //prints 2
}

Shouldn\'t the output of above pr

相关标签:
6条回答
  • 2021-01-26 15:19

    Undefined behavior aside, this is the behavior that you get with pointer arithmetic: when it is legal to subtract pointers, their difference represents the number of data items between the pointers. In case of int which on your system uses four bytes per int, the difference between pointers that are eight-bytes apart is (8 / 4), which works out to 2.

    Here is a version that has no undefined behavior:

    int data[10];
    int *p = &data[2];
    int *q = &data[0];
    // The difference between two pointers computed as pointer difference
    ptrdiff_t pdiff = p - q;
    intptr_t ip = (intptr_t)((void*)p);
    intptr_t iq = (intptr_t)((void*)q);
    // The difference between two pointers computed as integer difference
    int idiff = ip - iq;
    printf("%td %d\n", pdiff, idiff);
    

    Demo.

    0 讨论(0)
  • 2021-01-26 15:19

    According to the standard (N1570)

    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.

    0 讨论(0)
  • 2021-01-26 15:22

    These are integer pointers, sizeof(int) is 4. Pointer arithmetic is done in units of the size of the thing pointed to. Therefore the "raw" difference in bytes is divided by 4. Also, the result is a ptrdiff_t so %d is unlikely to cut it.

    But please note, what you are doing is technically undefined behaviour as Sourav points out. It works in the most common environments almost by accident. However, if p and q point into the same array, the behaviour is defined.

    int a[100];
    int *p = a + 23;
    int *q = a + 25;
    
    printf("0x%" PRIXPTR "\n", (uintptr_t)a); // some number
    printf("0x%" PRIXPTR "\n", (uintptr_t)p); // some number + 92
    printf("0x%" PRIXPTR "\n", (uintptr_t)q); // some number + 100
    printf("%ld\n", q - p); // 2
    
    0 讨论(0)
  • 2021-01-26 15:27
    int main() {
        int *p = 100;
        int *q = 92;
        printf("%d\n", p - q);  //prints 2
    }
    

    It is called pointer arthmetic what happens there.

    The value will be (100-92)/sizeof(int). In your case sizeof(int)=4.

    In ISO9899 pointer arithmetic is defined so for subtraction ptr-ptr. Chapter 6.5.6p9

    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.

    0 讨论(0)
  • 2021-01-26 15:34

    Your code is undefined behavior.

    You cannot simply subtract two "arbitrary" pointers. Quoting C11, chapter §6.5.6/P9

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

    Also, as mentioned above, if you correctly subtract two pointers, the result would be of type ptrdiff_t and you should use %td to print the result.


    That being said, the initialization

     int *p = 100;
    

    looks quite wrong itself !! To clarify, it does not store a value of 100 to the memory location pointed by (question: where does it point to?) p. It attempts to sets the pointer variable itself with an integer value of 100 which seems to be a constraint violation in itself.

    0 讨论(0)
  • 2021-01-26 15:40

    This

    int *p = 100;
    int *q = 92;
    

    is already invalid C. In C you cannot initialize pointers with arbitrary integer values. There's no implicit integer-to-pointer conversion in the language, aside from conversion from null-pointer constant 0. If you need to force a specific integer value into a pointer for some reason, you have to use an explicit cast (e.g. int *p = (int *) 100;).

    Even if your code somehow compiles, its behavior in not defined by C language, which means that there's no "should be" answer here.

    0 讨论(0)
提交回复
热议问题