【问题标题】:Automatic Storage class自动存储类
【发布时间】:2014-06-23 23:41:52
【问题描述】:

自动 Storage 在函数中使用不会重新初始化使用 auto 关键字声明的 i 变量.


Practice.c : main() 和 func() 在 Practice.c

#include <stdio.h>

main()
{
  func();
  func();
  func();
}


func()
{
  auto int i=1;
  printf("  i = %d",i);
  i=i+1;
}

编译后执行Practice.exe输出如下:

i = 1
i = 1
i = 1

每次 ma​​in() 调用 func() i 都会重新初始化为 1。这是正确的,因为 i 的范围在func() 块,当控件脱离 this 块时,i 的值丢失。因此,当我第二次调用此 func() 函数时,i 的值将重新初始化为 1

检查以下New.c程序。

New.c : 包含 ma​​in()func()

#include <stdio.h>

main()
{
  func();
  func();
  func();
  func();
  func();
  func();
  func();
  func();  
}


func()
{
  auto int i;
  printf("  i = %d",i);
  i=i+1;
}

为了确定,我调用了函数 func() 8 次。 但是在 New.c 中, i 没有被初始化。当我编译后执行这个程序时,它的输出如下:

i = 4201582
i = 4201583
i = 4201584
i = 4201585
i = 4201586
i = 4201587
i = 4201588
i = 4201589

输出显示每次调用的增量。这背后的确切原因是什么?

【问题讨论】:

  • 您正在从非常古老的 C 文本或非常过时的 C 文本中学习。虽然 auto 关键字在 C 中仍然存在,但基本上从未使用过。
  • @duskwuff 也许你是对的。我是初学者,知识很少,所以我从我所拥有的开始。但如果你能提供正确的理由,那真的很有帮助。

标签: c automatic-storage


【解决方案1】:

输出显示每次调用的增量。确切的原因是什么 这背后?

默认情况下不会初始化具有自动存储分配的变量,访问未初始化的变量是未定义的行为。这意味着无法推断出您的第二个程序的行为。

另外,请注意函数范围内变量的默认存储类是自动的。因此,您不需要auto 关键字来限定i 的定义。

// in function scope

auto int i;
// equivalent to
int i;

还有,说错了

那么,当我第二次调用这个 func() 函数时 i 的值将被重新初始化为 1。

变量i 未重新初始化。一旦包含它的函数返回,它就会超出范围。当再次调用该函数时,它会再次分配到堆栈上。 这并不意味着它分配在同一个内存地址上。

此外,您需要注意函数的返回类型和参数列表。隐式返回类型是int,空参数列表意味着没有关于参数的数量和类型的信息,这意味着该函数采用固定但未知数量的未知类型的参数。您应该始终在参数列表中明确提及void,以表示该函数不接受任何参数。

#include <stdio.h>

// prototype of the function func
void func(void);

// main should have one of the below signatures - 
// int main(void); or 
// int main(int argc, char *argv[]);
int main(void)
{
  func();
  func();
  func();
}

// explicitly mention void in the 
// parameter list to mean the function
// takes no argument
void func(void)
{
  // using auto keyword is redundant because 
  // local variables have automatic storage allocation
  int i = 1;
  printf("i = %d", i);
  i = i + 1;
}

【讨论】:

  • @user3591973 不客气 :) 另外,您需要注意函数的返回类型和参数列表。隐式返回类型是int,空参数列表意味着没有关于参数的数量和类型的信息,这意味着该函数采用固定但未知数量的未知类型的参数。您应该始终在参数列表中明确提及 void 以表示该函数不接受任何参数。
  • 这并不意味着它被分配在同一个内存地址上。 所以你的意思是当我第一次调用 func()i 提供了一个垃圾值,例如 i=12345 并存储在 22222 内存位置,当我第二次调用 func() 时,变量返回到原来的垃圾值的作用域并增加并变为i = 12346,但使用不同的内存位置来存储33333。 @ajay
  • @user3591973 是的,对。下次您调用func 时,i 可能会存储在与22222 不同的内存位置,并且可能具有不同的垃圾值 - 无论位模式恰好位于该内存地址。
【解决方案2】:

在第二种情况下,您使用 i 却从未初始化它。

因此该值未由语言定义。您看到值递增模式的事实是您正在使用的特定编译器的产物。

在第一次迭代中,您有一个看似随机的值,恰好位于i 表示的内存位置。您的函数会增加该内存位置的值,然后该内存位置恰好用于后续调用。

【讨论】:

  • 那么显示为输出的值是什么?它是垃圾值还是名为 i 的内存地址? @Eric J.
  • 是的,没错。代码i=i+1 会增加该位置的任何垃圾,然后恰好在下一次调用时重复使用相同的位置。
  • 所以垃圾值增加,而内存位置保持不变。输出中显示的值是垃圾值。我的解释正确吗?
  • 是的。并且内存位置保持不变的事实是偶然的。
猜你喜欢
  • 2016-11-01
  • 2019-04-22
  • 2018-04-15
  • 2020-12-05
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 2014-07-06
相关资源
最近更新 更多