我刚开始从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()
函数之外访问。这怎么可能?这是一个局部变量!
答案 0 :(得分:6)
不同的技术概念和术语是
“标识符的范围”(即声明的名称在哪里可见,以便可以使用)与
“对象的存储持续时间”,即我可以合法地访问构成对象的内存多长时间 - 通过任何可用的方式,指针,索引,附加标识符或其他。另一个词是“对象生命周期”。
所以说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)
“将局部数组定义为静态只会改变其生命周期,或者它也会改变其范围?”
答案 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段中,但局部变量存储在堆栈段
中