Yua*_*Wen 9 c pointers stack-memory
有如下代码:
int fun(){
char* pc = NULL;
{
char ac[100] = "addjfidsfsfds";
pc = ac;
}
...
pc[0] = 'd';
printf("%s\n", pc);
...
}
Run Code Online (Sandbox Code Playgroud)
那么,我可以pc在ac结束范围之后安全使用吗?因为我不确定分配的堆栈内存是否ac会被编译器重新分配用于其他用途.
理解您的缺陷与对象的存储持续时间有关.除非您使用线程,否则您有三种类型需要关注,静态,自动和已分配.通过char ac[100] = "addjfidsfsfds";在块内声明并且没有static存储类说明符,存储持续时间是自动的,并且它的生命周期在块的执行结束时结束.之后尝试访问该值的是Undefined Behavior.
C标准在第6.2.4节中详细说明了这一点,例如
1对象具有确定其生命周期的存储持续时间.有四个存储持续时间:静态,线程,自动和已分配.分配的存储在7.22.3中描述 .
2 对象的生命周期是程序执行的一部分,在此期间保证为其保留存储.一个对象存在,具有一个常量地址,33)并在其整个生命周期内保留其最后存储的值.34)如果一个对象在其生命周期之外被引用,则该行为是未定义的.当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定.
3声明标识符的对象没有存储类说明符_Thread_local,并且具有外部或内部链接或存储类说明符static,具有静态存储持续时间.它的生命周期是程序的整个执行,它的存储值只在程序启动之前初始化一次.
(省略了_Thread_local细节)
5声明标识符没有链接且没有存储类说明符静态的对象具有自动存储持续时间,一些复合文字也是如此.尝试从与对象关联的线程以外的线程间接访问具有自动存储持续时间的对象的结果是实现定义的.
6 对于没有可变长度数组类型的对象,其生命周期从entry进入与其关联的块,直到该块的执行以任何方式结束.(输入一个封闭的块或调用一个函数暂停,但不会结束,执行当前块.)如果以递归方式输入块,则每次都会创建一个新的对象实例.对象的初始值是不确定的.如果为对象指定了初始化,则每次在执行块时达到声明或复合文字时都会执行初始化; 否则,每次达到声明时,该值将变为不确定.
7对于具有可变长度数组类型的此类对象,其生命周期从对象的声明扩展,直到程序的执行离开声明的范围.35)如果以递归方式输入范围,则为对象的新实例每次创建.对象的初始值是不确定的.
如果对是否允许访问值存在疑问,请参阅标准.
来自C标准#6.2.1p4 [强调我的]
每个其他标识符的范围由其声明的位置(在声明符或类型说明符中)确定.如果声明标识符的声明符或类型说明符出现在任何块或参数列表之外,则标识符具有文件范围,该范围终止于转换单元的末尾.如果声明标识符的声明符或类型说明符出现在块内或函数定义中的参数声明列表中,则标识符具有块作用域,该作用域终止于关联块的末尾.......
变量ac是一个本地(自动)非静态变量,其生命周期仅限于其范围,即声明它的块.任何在其生命周期之外访问它的尝试都会导致未定义的行为.
来自C标准#6.2.4p2 [强调我的]
对象的生命周期是程序执行的一部分,在此期间保证为其保留存储.一个对象存在,具有一个常量地址,33)并在其整个生命周期内保留其最后存储的值.34)如果一个对象在其生命周期之外被引用,则该行为是未定义的.当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定.