【问题标题】:Is it possible for a variable in a function to hold an old value from old calls of the function in C?函数中的变量是否可以保存来自 C 中函数的旧调用的旧值?
【发布时间】:2017-06-02 00:29:18
【问题描述】:

我有这样的事情:

void test(int iter){    
  int i;    
  if(iter>3){    
    i=5;    
    printf("%d",i);    
  }else{    
    printf("%d",i);    
  }    
  return;    
}
int main(){
  test(5);
  test(2);
  return 1;
}

这只是一个例子。如果至少 iter 大于 3,那么当主变量 i 保持值 5(在内存中)时,是否有可能? 我知道这不正常。但是我的程序中有一个函数(我没有这样做的静态变量)。所以也许每次初始化这个变量的地址都是一样的(所以我得到的是旧值)?或者会发生什么?我不想保留旧值或其他东西。我只是好奇:这怎么可能?

【问题讨论】:

  • 您遇到的这种行为是错误的,还是您想要创建的行为?
  • 这是未定义的行为,因此显示的值可以是任何值(或没有或崩溃)。推理这种行为的一种方法是这个著名的 SO 答案:stackoverflow.com/a/6445794/12711

标签: c memory


【解决方案1】:

如果i 存储在堆栈的某个位置,并且如果该位置没有被修改,那么i 将保留它的值。

假设i甚至存储在堆栈上(优化可能会消除这一点),如果有使用堆栈的中断(或者可能由于时间片而发生上下文切换),堆栈指针下方的堆栈区域将被覆盖。一些编译器可能会填充堆栈区域,通常是在调试模式下。调试模式下的 Visual Studio 将使用上述代码捕获未初始化变量的使用情况。

【讨论】:

  • 因此,如果在调用之后,“i”的值作为垃圾在堆栈上,并且如果堆栈的这个地址不会被使用(由其他东西初始化)我的下一个测试调用在这种情况下, 将打印 5。如果 i 未初始化但定义在与以前相同的地址中并打印实际上是 5 的垃圾。这是对的吗?@rcgldr
  • @Theredone - 根据优化,i 甚至可能不会存储在堆栈中,而是在代码中替换为立即值。假设i 在堆栈上,那么中断或可能的上下文切换(时间片)可以修改i 的存储位置。如果i 存储在堆栈中,并且没有更改该位置的值,则将保留i 的值。
【解决方案2】:

在您向我们展示的这个示例中,您永远不会用值初始化 i,除非 iter > 3,否则它永远不会被赋值。

它的值是未定义的,直到您实际将其设置为某个值,您只能在“if then else”子句的“if”部分执行此操作。

因此,当 iter 为 3 或更少时,i 中可能有垃圾值是完全正常的。

【讨论】:

  • 在我初始化一次后,我每次都以某种方式获得 5。即使 iter 小于 3。但每次。所以我试图理解怎么可能。一次得到 5 可能会发生,但每次得到它有点奇怪。
  • 不,这不是真的。它可能是在不同设备上运行的不同值。可能每次都一样,是“未定义”,你不知道编译器是怎么写的。
【解决方案3】:

清除您的变量 Global(功能失效)。 例如:

int a=0;
void f(){
    a++; 
}

这样函数执行后值不会丢失。

【讨论】:

  • 首先不是问题的重点。 OP 想知道行为的解释,而不是存储变量的方法。其次,如果变量是函数 static 的本地变量,则比全局变量更好。
【解决方案4】:

Do this:

void test(int iter){    
  static int i;    
  if(iter>3){    
    i=5;    
    printf("%d",i);    
  }else{    
    printf("%d",i);    
  }    
  return;    
}
int main(){
  test(5);
  test(2);
  return 1;
}

注意static int i; 行中的static 关键字。

【讨论】:

  • 对不起,我回答错了问题。我的错。如果您可以将标题更改为类似以下内容:我遇到了这种奇怪的行为,其中函数中的变量保存了来自函数旧调用的旧值。这怎么可能?;这样可以避免一些错误的答案。
猜你喜欢
  • 1970-01-01
  • 2013-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多