我可以在其范围之外使用声明为局部变量的数组值吗?

Can I use values of array declared as local variable outside of its scope?

假设下面的简单代码:

int main(void){
  char *p;
  int i = 1;
  while(i){
    char str[] = "string";
    p = str;
    i = 0;
  }
  /* Can I use above string by using `p` in here? */
  return 0;
}

我将一个字符串(字符数组)声明为局部变量,仅在 while{} 中有效。但是我把它的数组地址保存到指针p里面,在while{}之外也是有效的。使用 p 可以使用 while{} 之外的字符串吗?

如果没问题,为什么会起作用?

Is it okay use the string outside while{} by using p?

。在 while 的范围内 p 指向 str 的第一个字符。在 while 之外没有 str,因此 p 指向的位置没有有效的内存位置。

str声明

中使用static存储class说明符可以达到预期的效果
static char str[] = "string";  

while 之外你可以使用 p

printf("%s\n", p);  

这是因为 static 在一个块中声明的变量在整个程序执行过程中驻留在相同的存储位置。

str 指向进程的只读(数据)区。您也可以使用 p 访问(读取)该数据。但是,尝试写入该位置将导致分段错误。

不,这不行。这就是所谓的悬挂指针。如果您在程序尝试重新使用该地址之前设法使用了内存,您仍然可以获得预期的结果。但是,如果再次使用该内存,您将得到意想不到的结果和非常难以定位的错误。

以这个为例,它可能不适用于所有编译器,但在 Xcode on OS X 中,我得到了这个结果:

pa: apples
pa: orange
po: orange

#include <stdio.h>
char *pa;
char *po;

void apples(void)
{
    char sa[]="apples";
    pa = sa;
    printf("pa: %s\n", pa);
}

void orange(void)
{
    char so[]="orange";
    po = so;
    printf("pa: %s\n", pa);
    printf("po: %s\n", po);
}

int main(void)
{
    apples();
    orange();
    return 0;
}

对 apples() 和 orange() 的每个函数调用随后都会增长然后缩小堆栈,您可以看到字符串(applesorange ) 最终位于堆栈上的相同内存位置。但是,一旦字符串超出范围,就无法保证字符串会在那里。这一招"works"到这里,可是很危险的

作为附加练习,尝试在调用 orange() 之后在 main() 中打印 po 的内容,在大多数情况下,字符串将随着调用而消失printf() 覆盖堆栈上的 space。