Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 可变长度阵列存储持续时间_C_Scope - Fatal编程技术网

C 可变长度阵列存储持续时间

C 可变长度阵列存储持续时间,c,scope,C,Scope,现场有以下段落(重点): 自动存储持续时间。当声明对象的块被输入时分配存储,当它以任何方式退出时(转到、返回、到达终点)释放存储。一个例外是VLAs;它们的存储是在执行声明时分配的,而不是在块条目上,当声明超出范围时,而不是在块退出时(自C99起)释放。如果以递归方式输入块,则为每个递归级别执行新的分配。所有函数参数和非静态块作用域对象都具有此存储持续时间,以及块作用域中使用的复合文字 超出范围的声明和退出的块之间有什么区别?您能提供C11规范§6.2.4/7的N1570草案中的示例吗 对于

现场有以下段落(重点):

  • 自动存储持续时间。当声明对象的块被输入时分配存储,当它以任何方式退出时(转到、返回、到达终点)释放存储。一个例外是VLAs;它们的存储是在执行声明时分配的,而不是在块条目上,当声明超出范围时,而不是在块退出时(自C99起)释放。如果以递归方式输入块,则为每个递归级别执行新的分配。所有函数参数和非静态块作用域对象都具有此存储持续时间,以及块作用域中使用的复合文字

超出范围的声明和退出的块之间有什么区别?您能提供C11规范§6.2.4/7的N1570草案中的示例吗

对于具有可变长度数组类型的对象,其 生命周期从对象的声明一直延续到 程序将离开声明的范围

规范随后添加了以下有用的注释:

离开包含声明的最内层块,或跳转到 声明之前该块或嵌入块中的点, 保留声明的范围

因此,当执行超出VLA的范围时,VLA被取消分配,VLA的范围包括VLA声明之前同一块中的部分

可以使用
goto
语句跳转到声明之前的某个点。例如:

int n = 0;
while (n < 5)
{
top:
    n++;
    char array[n];
    if (n < 2)
        goto top;
}
int n=0;
而(n<5)
{
顶部:
n++;
字符数组[n];
if(n<2)
转到顶端;
}
在该代码中,当执行
goto
时,块不会退出。但是,
n
的值会发生变化,因此需要分配一个新的
数组。这就是规范试图支持的可怕的复杂情况

超出范围的声明和退出的块之间有什么区别?你能举个例子吗

块范围标识符的范围从其声明开始,并扩展到最内层封闭块的末尾。这适用于各种标识符,而不仅仅是VLA的标识符。通过转移到标识符声明之前的点,控件可以离开标识符的作用域而不退出包含它的最内层块。实现这一点最明显的方法是通过
goto
语句:

int f(int n) {
    // i is allocated here, _before_ the beginning of its scope
    label: // if control returns here via the goto below, vla is _de_allocated
           // at this point
    printf("n is %d", n);

    int vla[n]; // vla is (re)allocated here, at the beginning of its scope
    int i;
    int sum;

    for (i = 0; i < n; i++) {
        vla[i] = rand();
        sum += vla[i];
    }

    if (sum < SOME_THRESHOLD) goto label; 

    return sum;  // vla and i are both deallocated when control exits the block
}
intf(intn){
//我被分配在这里,在它的范围开始之前
label://如果控件通过下面的goto返回此处,则vla已分配
//此时
printf(“n是%d”,n);
int vla[n];//vla在其作用域的开始处(重新)分配到这里
int i;
整数和;
对于(i=0;i

解除分配VLA与解除分配普通自动对象时的差异反映了分配两种类型对象时的差异。VLA仅在其标识符的范围内活动。

请参阅关于可变长度数组的部分。它有一个很好的例子。@DeiDei我读过这个例子,但没有具体说明两者之间的区别。我只能认为在块的末尾有一条特殊指令,负责为VLA分配内存。因此,如果使用
返回
转到
退出块,则不会取消分配内存。这是对的吗?基本上这是给所有意大利面编码员的注释。如果你写的代码是合理的,你就不需要关心这个。谢谢。因此,当执行超出VLA的范围时,VLA将被取消分配,VLA的范围包括VLA声明之前同一块中的部分。@user42768是的,这是一个很好的表达方式。如果我把这条评论复制到答案中可以吗?当然,任何能让未来读者更好理解这一点的东西都可以。假设形式定义使用不同的词,真实的机器代码不同。函数返回后,堆栈上的Belive帧递减(即内部块中的变量在高级语言中没有意义,但堆栈未MIDIZED)。相反,@JacekCz,在机器代码中与其声明相对应的一点之前,堆栈空间很可能没有为VLA保留,因为它的大小可以取决于同一块中该声明前面的代码。当VLA超出范围时,该空间确实被释放也是合理的,因为它在重新分配时可能有不同的大小。谢谢。我对你的答案投了赞成票,但我只能接受一个,而@user3386109的答案是第一个。