我试图在代码中找到一个像这样的错误:
char *** read_set(char * filename)
{
int ch;
while(ch!=EOF)
{
//code...
}
//mode code...
}
在第一个调用中,它按预期工作,但在第二个调用中,ch是EOF(-1)。当然我应该初始化它,但我不希望局部变量将被分配相同的地址。这是总是发生的事情还是依赖于os /编译器等?
答案 0 :(得分:3)
这是正常的,特别是如果您多次从同一个来电者调用该功能,例如
read_set("foo");
read_set("bar");
read_set("baz");
或
for (i = 0; i < 5; ++i) {
read_set(filenames[i]);
}
堆栈包含返回地址,帧指针,局部变量,参数值和每个活动函数调用的临时值(从main
开始)。所有这些都具有每个函数的固定大小是很常见的,所以如果函数A()在堆栈上需要40个字节,函数B()需要20个字节而函数C()需要1000个字节,那么在在以下两种情况下,read_set的局部变量(例如&ch
)通常位于同一地址:
main()调用C(),C()调用B(),B()再次调用B(),内部B()调用read_set()。
main()调用C(),C()调用A(),A()调用read_set()。
请注意,根据编译器和架构,您可能会获得不同的地址。但获得相同的地址并不罕见。
请注意,某些安全功能(如地址空间随机化)可能会在您每次再次运行程序时为您提供不同的地址。但是在同一次运行中,你会获得相同的地址。
答案 1 :(得分:1)
宣言:
int ch;
相当于:
auto int ch;
暗示auto
部分;在函数内声明变量时默认为默认值。 auto
变量存储在进程堆栈中,并且它们在堆栈上占用的内存在从函数返回时用于其他目的。因此,scope
自动变量仅限于执行函数的时刻。
从函数的一次调用到下一次调用,这样的auto
(基于堆栈)变量的地址不一致。它取决于在调用函数之前放置(或从中拉出)的内容。
可以声明一个变量,该变量将从函数的一次调用中保持其值到下一个;但该变量不会存储在堆栈中。声明这样的变量,必须从默认的auto
类型切换到static
类型:
static int ch;
你是对的;你应该用一个初始值初始化这样一个变量:
static int ch = 0;
在函数中声明一个静态变量会导致编译器在程序执行期间为该变量赋予它自己的永久内存位置。因此,它的地址不会从函数的一次调用改变到下一次。