简单C程序上的奇怪输出

时间:2013-02-19 11:02:32

标签: c

我在C中有以下内容:

int x = 0;
int *a = &x;

void foo(int *a)
{
    static int x = 0;
    x++;
    *a += x;
    a = &x;
    *a = x + 10;
}

int _tmain(int argc, _TCHAR* argv[])
{
    foo(a);
    foo(a);
    printf("%d\n", *a);

    return 0;
}

我可以清楚地调试它并看到行*a += x没有做任何事情,而且我可以看到x在离开函数之前仅一秒钟的值是22并打印出来out 13

当我在脑子里做的时候,我已经34岁了,据我所知,这应该是正确的答案。 有人可以解释我可能错在哪里吗?

4 个答案:

答案 0 :(得分:7)

让我们一步一步来做。

第一轮:

int x = 0; // global "x"

static int x = 0; // local "x" = 0
x++; // local "x" = 1
*a += x; // global "x" += local "x" results in global "x" = 1
a = &x; // local "a" points to local "x"
*a = x + 10; // local "x" = local "x" + 10 results in local "x" = 11

第二轮:

int x = 0; // global "x" = 1 now

static int x = 0; // local "x" = 11 now
x++; // local "x" = 12
*a += x; // global "x" += local "x" results in global "x" = 13
a = &x; // local "a" points to local "x"
*a = x + 10; // local "x" = local "x" + 10 results in local "x" = 22

printf("%d\n", *a); // prints global "x", 13

答案 1 :(得分:2)

这很容易。棘手的部分是识别x的不同副本,以及函数内a的范围。

void foo(int *a)
{
    static int x = 0;
    x++;
    *a += x;
     a = &x;   //<==== this doesn't change the a outside you see, a now points to static x
    *a = x + 10;
 }

单步执行gdb应该告诉你实际发生了什么。 请注意,在上面标记的行上,static int x已更改。所以*a=x+10;实际上更改了static int x。所以在第一次迭代之后:

全球x = 1静态x = 11

所以在第二次迭代中 静态x增加到12,然后增加到全局x=1+12;。这使全局x==13。其余代码不再影响全局x和全局afoo然后只需将静态x加10,这与全局变量无关。

答案 2 :(得分:0)

这样可以更容易地看到

int x = 0;
int *a = &x;

void foo(int *a)
{
    static int y = 0;
    y++;
    *a += y;

      a = &y;        // a doesn't point to x anymore!!!
    *a = y + 10;
}
int _tmain(int argc, _TCHAR* argv[])
{
    foo(a);
    foo(a); // Now 'a' again points to the global 'x' (once more) 
    printf("%d\n", *a);

    return 0;
}

答案 3 :(得分:0)

由于C使用静态范围,当有两个具有相同名称的变量时,它将首先用于当前块中声明的变量,然后它将查看外部块。所以static int x会影响全局变量x。还有一点需要注意的是,C参数是按值传递的,因此如果指定值的副本,则不会影响原始值。

让我们假设一个全局变量x的地址为0x8000,静态变量x的地址为0x9000的情况。这是第一次通话时发生的情况:

void foo(int *a)  // a= 0x8000 , global int x=0
{
    static int x = 0;
    x++;         // static int x=1
    *a += x;     // global int x=1
    a = &x;      // a=0x9000 (only a copy of a is assigned, so the global a will remain 0x8000)
    *a = x + 10;     // static int x= 11
}

这就是第二次电话会议中发生的事情:

void foo(int *a)  // a= 0x8000 , global int x=1, static int x=11
{
    static int x = 0;
    x++;         // static int x=12
    *a += x;     // global int x= 13
    a = &x;      // a=0x9000
    *a = x + 10;     // static int x= 22
}