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的范围。