C 堆栈分配的字符串作用域

标签 c pointers scope stack cstring

对于直接的 C 和 GCC,为什么指向的字符串在这里没有被破坏?

#include <stdio.h>

int main(int argc, char *argv[])
{
    char* str_ptr = NULL; 

    {
        //local to this scope-block
        char str[4]={0};
        sprintf(str, "AGH"); 

        str_ptr = str;
    }

    printf("str_ptr: %s\n", str_ptr);

    getchar();
    return 0;
}

|----输出-----|

str_ptr: AGH

|--------------------|

这是 a link使用在线编译器编译和执行上述代码。

我知道如果 str 是字符串文字,str 将存储在 bss 中(本质上是静态的),但是 sprintf(ing) 到堆栈-分配的缓冲区,我认为字符串缓冲区将是纯粹基于堆栈的(因此地址在离开范围 block 后毫无意义)?我知道可能需要额外的堆栈分配来覆盖给定地址处的内存,但即使在发生堆栈溢出之前使用递归函数,我也无法破坏 str_ptr 指向的字符串>.

仅供引用,我正在 VS2008 C 项目中进行测试,尽管 GCC 似乎表现出相同的行为。

最佳答案

虽然鼻蜥蜴是 C 民间传说的一个流行部分,但其行为未定义的代码实际上可以表现出任何行为,包括神奇地复苏其生命周期已过期的变量。具有未定义行为的代码可能看起来“有效”这一事实既不应令人惊讶,也不应成为忽视纠正它的借口。一般来说,除非您从事编写编译器的工作,否则在任何给定环境中检查未定义行为的确切性质并不是很有用,尤其是当您眨眼之后它可能会有所不同。

在这种特殊情况下,解释很简单,但它仍然是未定义的行为,因此根本不能依赖以下解释。它可能随时被爬行动物排放物取代。

一般来说,C 编译器会使每个函数的堆栈帧具有固定大小,而不是随着控制流进入和离开内部 block 而扩展和收缩。除非被调用的函数是内联的,否则它们的栈帧不会与调用者的栈帧重叠。

因此,在某些具有特定编译选项集的 C 编译器中,除了特定的月相之外,字符数组 str 不会被调用 printf,即使变量的生命周期已过期。

关于C 堆栈分配的字符串作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17984314/

相关文章:

c - 不明白 "....*(BYTE *)p=0xff;...."这样的一段代码

c - MPI_Isend请求参数

node.js - 同一模块的多个需求似乎会影响每个连续需求的范围

javascript - 尝试添加多个 D3 图

Java数据字段封装newby问题

java - 计算从 167.37 美元中赚取(钱)零钱的不同方式?

C 函数指针 - 当你放弃一个参数时会发生什么?

c - 临时指针 : Correct malloc and free

c - 读取纺织品并添加到 C 中的链接列表

c - 是可变指针数组还是指向数组的指针?