我在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岁了,据我所知,这应该是正确的答案。 有人可以解释我可能错在哪里吗?
答案 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
和全局a
。 foo
然后只需将静态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
}