简体   繁体   中英

Weird output on a simple C program

I have the following come in 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;
}

I can clearly debug it and see that the line *a += x doesn't do anything plus I can see that the value of x just a second before going out of the function is 22 and it prints out 13 .

When I did it in my head, I've go 34, which should be the right answer as far as I can see. Can somebody explain where I might be wrong?

Let's do it step by step.

First round:

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

Second round:

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

It's easy. The tricky part is to recognize the different copies of x , and the scope of a inside the function.

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;
 }

Single stepping it in a gdb should tell you what actually happens. Just notice that on the line marked above, the static int x is changed. so the *a=x+10; actually changes the static int x . So after the first iteration:

Global x =1 static x =11

So in the second iteration static x is incremented to 12 , then global x=1+12; . this makes global x==13 . The rest of the code doesn't affect global x and global a anymore. The foo then simply adds the static x by 10, which is irrelevant to the global variable.

This makes it easier to see

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;
}

Since C uses static scope, when there are two variables with the same name, it will be used first the one declared in the current block, then it will look at external blocks. So static int x shadows the global variable x. Also another thing that you should note is that in C arguments are passed by value, so if you assign a copy of the value you don't affect the original value.

Let's imagine a case where the global variable x has address 0x8000 , and the static variable x is at address 0x9000. This is what happens at the first call:

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
}

And this is what happens in the second call:

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM