無效的指標算術

指標演算法的以下用法會導致未定義的行為:

  • 如果結果不屬於與指標運算元相同的陣列物件,則新增或減去整數。 (這裡,結尾的元素被認為仍然屬於陣列。)

    int a[10];
    int* p1 = &a[5];
    int* p2 = p1 + 4; // ok; p2 points to a[9]
    int* p3 = p1 + 5; // ok; p2 points to one past the end of a
    int* p4 = p1 + 6; // UB
    int* p5 = p1 - 5; // ok; p2 points to a[0]
    int* p6 = p1 - 6; // UB
    int* p7 = p3 - 5; // ok; p7 points to a[5]
    
  • 如果它們不屬於同一個陣列物件,則減去兩個指標。 (同樣,超過結尾的元素被認為屬於陣列。)例外是可以減去兩個空指標,產生 0。

    int a[10];
    int b[10];
    int *p1 = &a[8], *p2 = &a[3];
    int d1 = p1 - p2; // yields 5
    int *p3 = p1 + 2; // ok; p3 points to one past the end of a
    int d2 = p3 - p2; // yields 7
    int *p4 = &b[0];
    int d3 = p4 - p1; // UB
    
  • 如果結果溢位 std::ptrdiff_t,則減去兩個指標。

  • 任何指標運算,其中運算元的指標型別與指向的物件的動態型別不匹配(忽略 cv-qualification)。根據標準,“[特別是,當陣列包含派生類型別的物件時,指向基類的指標不能用於指標算術。”

    struct Base { int x; };
    struct Derived : Base { int y; };
    Derived a[10];
    Base* p1 = &a[1];           // ok
    Base* p2 = p1 + 1;          // UB; p1 points to Derived
    Base* p3 = p1 - 1;          // likewise
    Base* p4 = &a[2];           // ok
    auto p5 = p4 - p1;          // UB; p4 and p1 point to Derived
    const Derived* p6 = &a[1];
    const Derived* p7 = p6 + 1; // ok; cv-qualifiers don't matter