为什么print语句会改变指针的值?

pir*_*atf 4 c++ pointers c++11

我写了一个像这样的c ++代码:

#include <iostream>
using namespace std;

int main() {
    int i = 2;
    int i2 = 0;
    void *pi = &i - 1;
    cout << "by cout - the value of *pi is: " << *(int*)pi << endl;
    printf("by printf - the value of *pi is: %d\n", *(int*)pi);
    printf("the address of pi is: %p\n", pi);
    printf("the address of i2 is: %p\n", (void*)&i2);
    printf("the value of i2 is: %d\n", i2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

by cout - the value of *pi is: 0
by printf - the value of *pi is: 0
the address of pi is: 0029fe94
the address of i2 is: 0029fe94
the value of i2 is: 0
Run Code Online (Sandbox Code Playgroud)

现在,如果我删除将打印地址的语句.

#include <iostream>
using namespace std;

int main() {
    int i = 2;
    int i2 = 0;
    void *pi = &i - 1;
    cout << "by cout - the value of *pi is: " << *(int*)pi << endl;
    printf("by printf - the value of *pi is: %d\n", *(int*)pi);
    // printf("the address of pi is: %p\n", pi);
    // printf("the address of i2 is: %p\n", (void*)&i2);
    printf("the value of i2 is: %d\n", i2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在输出是:

by cout - the value of *pi is: 2004212408
by printf - the value of *pi is: 2004212408
the value of i2 is: 0
Run Code Online (Sandbox Code Playgroud)

注意到价值完全不同.

更新:如果我在打印后添加一些作业:

#include <iostream>
using namespace std;

int main() {
    int i = 2;
    int i2 = 0;
    void *pi = &i - 1;
    cout << "by cout - the value of *pi is: " << *(int*)pi << endl;
    printf("by printf - the value of *pi is: %d\n", *(int*)pi);
    // printf("the address of pi is: %p\n", pi);
    // printf("the address of i2 is: %p\n", (void*)&i2);
    pi = &i2;
    printf("the value of i2 is: %d\n", i2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出再次正常:

by cout - the value of *pi is: 0
by printf - the value of *pi is: 0
the value of i2 is: 0
Run Code Online (Sandbox Code Playgroud)

使用"g ++ -std = c ++ 11 -pedantic -Wall"进行编译,版本为4.9.2.

为什么会这样?

Sho*_*hoe 8

pi由于&i - 1可能不是有效的指针值,因此访问是未定义的行为.

在标准(来自C++标准)中,在§5.3.1/ 3中我们有:

[...]出于指针运算(5.7)和比较(5.9,5.10)的目的,不是以这种方式获取地址的数组元素的对象被认为属于具有T类型的一个元素的数组.

这导致我们§5.7/ 4:

当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型.如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式.[...]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.

  • 我认为减法本身已经是UB. (4认同)
  • 基本上,C++程序中的每个问题都可以用未定义的行为来解释. (2认同)