C 本地定义的数组在其定义的函数之外是否有效?
如果我们在C 本地定义的数组在其定义的函数之外是否有效?,c,arrays,memory,scope,lifetime,C,Arrays,Memory,Scope,Lifetime,如果我们在SomeFunction中定义一个数组,它在其范围内是有效的。但是它实际上存储在哪里呢?局部变量通常存储在堆栈上,但我一直在问自己,是整个数组存储在堆栈上,还是只指向数据字段的指针,数据字段实际上存储在那里(比如调用malloc在堆上分配内存)。讨论在微控制器中的实现 所以这个问题也引出了另一个问题。如果数据存储在堆中,如果指针将保存到pdata并在不同的作用域(SomeOtherFunction)中访问,则该操作是否有效?数据是否可以在那里使用,或者我如何知道数据是否不再有效 #de
SomeFunction
中定义一个数组,它在其范围内是有效的。但是它实际上存储在哪里呢?局部变量通常存储在堆栈上,但我一直在问自己,是整个数组存储在堆栈上,还是只指向数据字段的指针,数据字段实际上存储在那里(比如调用malloc在堆上分配内存)。讨论在微控制器中的实现
所以这个问题也引出了另一个问题。如果数据存储在堆中,如果指针将保存到pdata
并在不同的作用域(SomeOtherFunction
)中访问,则该操作是否有效?数据是否可以在那里使用,或者我如何知道数据是否不再有效
#define DATAFIELDLEN 127
static uint8_t* pdata;
static void SomeFunction()
{
uint8_t dataField[DATAFIELDLEN] = {};
// Write some stuff to the datafield
pdata = dataField; // Save pointer to the datafield
}
static void SomeOtherFunction()
{
// Use datafield here
for(uint8_t ii=0; ii<DATAFIELDLEN; ii++){
// Dereference Data here
someOperation(pdata[ii]); // <-------- is the data valid here?
}
}
void main()
{
SomeFunction();
SomeOtherFunction();
}
#定义数据字段len 127
静态uint8_t*pdata;
静态函数()
{
uint8_t数据字段[DATAFIELDLEN]={};
//在数据字段中写入一些内容
pdata=dataField;//保存指向数据字段的指针
}
静态void SomeOtherFunction()
{
//在这里使用数据字段
对于(uint8_t ii=0;iiNo,数据字段
是函数SomeFunction()
的本地字段。一旦函数完成执行,就不存在数据字段
在函数外部访问数据字段
的任何方法(将其保存到全局指针,返回指针,然后在调用者中使用)都将导致无效的内存访问,从而调用
为了对此进行详细说明,请引用C11
标准,第§6.2.4章,对象的存储期限,(重点是我的)
对象的生存期是程序执行期间存储被删除的部分
保证为其保留。对象存在,具有恒定地址,33)并保留
它在整个生命周期中的最后一个存储值。34)如果对象在其外部被引用
在生命周期内,行为未定义。当
它指向(或刚刚过去)的对象已到达其生命周期的终点。
另外,对于自动局部变量
一种对象,其标识符声明时没有链接,也没有存储类
说明符static
具有自动存储持续时间,[…]对于没有可变长度数组类型的对象,其生存期将延长
从进入与其关联的块,直到该块的执行在
无论如何
不,那里的数据是无效的。你可以让它有点有效,但它真的很危险。让我解释一下
在SomeFunction()中分配数组时
它是在堆栈上分配的。这意味着一旦您从该函数返回,在将来使用堆栈时,内存将在某个时候被覆盖。您可能会将指针解引用到一个您并不真正控制的内存区域中。有时您可能会侥幸逃脱,但它肯定是未定义的行为r
另一方面,虽然确实不建议,但您可以将该数组标记为静态
。如果这样做,它将不再在堆栈上分配,并且当它超出范围时,您可以继续访问它。请明确,我不建议将其作为一个好的解决方案
使此保留有效的正确方法是malloc()
它的内存,并用pdata
指向它,为什么不查找C11标准草案,6.2.4对象的存储持续时间?
?“本地”是范围问题,而不是生存期问题。不要将其与自动变量混淆!即使他会使用malloc()
,我希望他不会忘记使用free()
在它之后。当然……某种程度上认为它是不言而喻的。这种数组在应用程序期间存在的另一种方式是,如果声明之后的代码进入一个无休止的循环,可能是围绕一个阻塞的系统调用。这并不少见,但超出了C的范围。