在函数外部操作一个本地静态指针变量,该变量在函数内定义。

3

我想访问和修改一个在全局作用域定义的函数中的静态变量,但是输出的第二行和第三行是意外的,为什么ox是0?

#include <iostream>

using namespace std;

int * foo(){
    static int *x = new int(5);
    cout << *x << '\t' << &x << endl;
    *x++;
    return x;
}

int main(){
    int * ox;
    ox = foo();
    cout << *ox << '\t' << &ox << endl;
    *ox++;
    cout << *ox << '\t' << &ox << endl;
    int * t= foo();
}

输出结果为(在我的机器上):
5   0x6021d0
0   0x7fffdc82d3a0
0   0x7fffdc82d3a0
0   0x6021d0

欢迎提出任何意见。

2个回答

4

操作顺序。您两次执行*ox ++;

这不是评估为(* ox) ++“增加指向的值”

它是*(ox ++) “增加指针”

为什么ox为0?

ox恰巧指向0。您已将其递增以指向您不拥有的内存。


谢谢!我太粗心了 :) - Myzh
@Myzh 没关系!还可以看看5gon12eder的回答,他比我先注意到你也在打印"指针的地址"...给他一个赞。:) - Drew Dormann

3

您遇到了一些解析问题。让我们逐行查看代码:

static int * x = new int(5);

第一次控制流经过这条线时,x被赋予一个指向新分配的、初始化为5的int的指针。每次控制流再次经过时,这行代码都将“跳过”。到目前为止还没有什么意外。

cout << *x << '\t' << &x << endl;

我猜您想打印值的地址,而不是指针的地址,因此应输入:
cout << *x << '\t' << x << endl;

现在变得有趣了。这行代码可能不会做你想要的事情。

*x++;

编译器将其解析为*(x++)。这意味着指针x被推进并且其先前的值被取消引用,结果被丢弃。(下次进入函数时会引发未定义的行为,因为现在x指向已分配内存位置的后一个位置。)您可能认为它应该被解析为(*x)++,这将增加指向x的值。对于您的main也是同样的模式。
如果我使用GCC编译您的原始代码并传递-Wall标志(这总是一个好主意),它会给我们一个很好的提示,说明发生了什么:
main.cpp: In function ‘int* foo()’:
main.cpp:8:7: warning: value computed is not used [-Wunused-value]
   *x++;
       ^

main.cpp: In function ‘int main()’:
main.cpp:16:8: warning: value computed is not used [-Wunused-value]
   *ox++;
        ^

1
@5gin12eder 不,*x++使用后缀运算符的临时变量进行解引用,它不会解引用已经增加的指针。实际上,它被解析为 *(x++),但 (x++) 的结果是一个等于旧的 x 的临时变量。 - vsoftco
@vsoftco 哦,你说得对。我忽略了那个。未定义的行为会在下一次解引用指针时出现。 - 5gon12eder
很好的发现,注意到了 &x - Drew Dormann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接