这个数组定义为静态而非全局?

时间:2015-07-12 09:06:54

标签: c arrays

我刚开始从here学习C语言。

在我上面链接的部分中,作者希望从函数返回一个数组,并写道:

  

C不主张将局部变量的地址返回给   在函数之外,所以你必须定义局部变量   作为静态变量。

我理解阻止返回局部变量地址的原因。原因是局部变量在其范围之外是不可用的,因此将其地址置于函数之外可能会在运行时产生错误。

但我不明白的部分是为什么我们必须定义数组静态而不是全球

将局部数组定义为静态只会改变其生命周期,也会改变其范围?

这是我谈到的程序:

#include <stdio.h>

/* function to generate and return random numbers */
int * getRandom( )
{
  static int  r[10];
  int i;

  /* set the seed */
  srand( (unsigned)time( NULL ) );
  for ( i = 0; i < 10; ++i)
  {
     r[i] = rand();
     printf( "r[%d] = %d\n", i, r[i]);

  }

  return r;
}

/* main function to call above defined function */
int main ()
{
   /* a pointer to an int */
   int *p;
   int i;

   p = getRandom();
   for ( i = 0; i < 10; i++ )
   {
       printf( "*(p + %d) : %d\n", i, *(p + i));
   }

   return 0;
}

更新

这是以上程序的输出:

r[0] = 313959809
r[1] = 1759055877
r[2] = 1113101911
r[3] = 2133832223
r[4] = 2073354073
r[5] = 167288147
r[6] = 1827471542
r[7] = 834791014
r[8] = 1901409888
r[9] = 1990469526
*(p + 0) : 313959809
*(p + 1) : 1759055877
*(p + 2) : 1113101911
*(p + 3) : 2133832223
*(p + 4) : 2073354073
*(p + 5) : 167288147
*(p + 6) : 1827471542
*(p + 7) : 834791014
*(p + 8) : 1901409888
*(p + 9) : 1990469526

如上所述,该数组可以在getRandom()函数之外访问。这怎么可能?这是一个局部变量!

4 个答案:

答案 0 :(得分:6)

不同的技术概念和术语是

  1. “标识符的范围”(即声明的名称在哪里可见,以便可以使用)与

  2. “对象的存储持续时间”,即我可以合法地访问构成对象的内存多长时间 - 通过任何可用的方式,指针,索引,附加标识符或其他。另一个词是“对象生命周期”。

  3. 所以说int *p = getRandom();你引入了一个带有块范围的标识符(因为它在main中),用自动存储持续时间来识别指针对象(因为它被声明没有任何存储或链接资格,如“extern”或“静态”)。对于p,对象生命周期和标识符范围是相同的:块p在声明和定义中。

    存储在此本地指针对象中的是数组r中具有静态存储持续时间的元素的地址。在r中声明并定义了getRandom()。标识符r范围是声明它的getRandom()正文的块;您无法在其他地方使用此名称 r。但由于“存储类说明符”静态,数组对象本身具有静态存储持续时间。这意味着数组对象的生命周期是程序的生命周期。 (是的,它甚至在getRandom()运行之前就已存在,但我认为没有办法合法访问它。)这就是为什么你可以在任何地方泄露其地址并使用它,即使getRandom()有很久以来就回来了。

    编辑:为了完整性:为什么有人会这样做而不只是声明数组的全局标识符?嗯,这是封装的早期形式(getRandom()的后续实现可能不同),这是实现单例的一种方式。

    我怎么知道?我读了freely available C standard draft。一如既往,找到相关信息并不容易,但简单的关键字搜索有所帮助。相关的是标识符范围的6.2.1和对象的存储持续时间的6.2.4。当然,标准是干燥和正式的,但它引入了适当的术语,并且在一些适应性之后,是非常容易理解的。

答案 1 :(得分:2)

“将局部数组定义为静态只会改变其生命周期,或者它也会改变其范围?”

  • 范围永远不会改变。
  • 但是生命周期的变化:制作一个局部变量 static 会使它持续一段时间。

答案 2 :(得分:0)

在程序的持续时间内存在静态局部变量,但仅在函数体中可见。 即使在定义它们的块终止之后,静态变量仍然存在。 因此,在对同一函数的重复函数调用之间保留函数中静态变量的值。

So, It will change the lifetime , but leaves scope as it is i.e local to the function 

答案 3 :(得分:0)

局部变量和静态变量之间的主要区别是

1)静态变量在程序期间持续

2)静态变量存储在BSS段中,但局部变量存储在堆栈段