本地指针存储在内存中的哪个位置?

时间:2012-07-14 04:40:15

标签: c pointers

我是C的初学者。我有一个程序如下:

int main()
{
    char* func();
    char *c;
    c = func();
    printf("%s", c);
}

char* func()
{
    char *ptr = "OK";
    return ptr;
}

众所周知,ptrfunc()的局部变量,是一个指针。范围是本地的。 但是当ptr返回给调用者main时,它仍然有效,并且在打印c时,它会打印"确定"。

这怎么可能?在哪个内存段中存储ptr;堆栈还是堆?

8 个答案:

答案 0 :(得分:7)

这是使用指针时的内幕(注意指针就像名字所暗示的那样,就像手指指向某个东西)。

让我们分解您的代码并逐步理解它。 在main函数中,您声明了一个字符指针* c

char *c;

然后你这样做了:

c = func();

告诉c指针指向func()指向的内容。

让我们来看看你的功能

char* func()
{
    char *ptr = "OK";
    return ptr;
}

第一行再次声明一个字符指针ptr,并为该地址指定“OK”(注意:指针只指向某个存储器地址)。所以现在,该地址包含字符串“OK”(或者更准确地说,是一个char数组)。

然后返回ptr,这是“OK”所在的地址。请注意,因为ptr是在func()中声明的,所以它是一个局部变量。因此,一旦返回,它将从堆栈(poof!Gone)中删除。

但是,因为在你的main()中:

c = func(); 

变量c指向存储“OK”的地址。因此,即使变量ptr不再存在,变量c也知道它在哪里,并且仍然可以访问“OK”。

回答你的问题:

  • ptr存储在堆栈
  • 退出func()时,
  • 和ptr从堆栈中弹出

答案 1 :(得分:4)

让我们暂时忘记堆栈/堆栈。我们来聊聊C。

ptr之外的本地变量func不存在,因此调用者不能且不应引用

但是C doesn't do pass by reference。一切都是通过价值传递的。 func会将ptr中存储的返回给其调用者。就像你会返回int或任何其他类型的一样。

因此,对于您的示例,ptr的值是名为"OK"的字符串文字的地址。并且string literals are valid during the entire scope of the program。因此func返回字符串文字的地址,允许在程序中的任何位置取消引用。

为了更清楚,func相当于:

const char * func (void)
{
  return "OK";
}

这就是为什么一切都很好。

知道以下情况还可以:

const char * func (void)
{
  char *ptr = "OK";
  return ptr;
}

这不是:

const char * func (void)
{
  char ptr[] = "OK";
  return ptr;
}

不行,因为现在你正在返回指向 local func的数组的指针。

还有一个小问题。它应该是:const char * func (),因为"OK"不允许修改。

答案 2 :(得分:2)

当您调用该函数时,其所有局部变量和返回地址都会推送到堆栈。所以ptr将在堆栈中,但是“OK”-string在常量数据部分。当您从func返回时,ptr的值已分配给c变量,ptr不再存在(实际存在),但其值存储在{ {1}}。

答案 3 :(得分:1)

文本"OK"存储在可执行文件的常量数据部分中(在启动进程时将其加载到内存中)。虽然ptr是局部变量,但编译器会将其初始化为指向存储在其他位置的"OK"。当您将ptr返回给调用者时,指针仍然指向相同的"OK"

答案 4 :(得分:1)

如果您指的是字符串OK的存储位置,则其存储在内存的 code部分中,而ptr则存储在堆栈

由于OK返回了其地址,因此func()在代码部分的位置仍然可以访问。

此外,代码部分为只读。这就是为什么其他答案建议将函数声明为:

的原因
const char * func ()

这确保返回的地址所指向的值不可修改。 (指向常量的指针)

答案 5 :(得分:0)

ptr保存常量数据部分中"OK"数据的地址。这是返回的地址。不是ptr的地址即使ptr不再存在,"OK"仍然存在

答案 6 :(得分:0)

char *ptr = "OK"; - 该语句将为变量ptr分配4个字节(如果它是32位机器),它将保存字符串文字OK的地址。现在ptr具有字符串OK的起始地址(4字节)(实际上是3个字节,包括\0)。这3个字节的字符串OK将位于文本段中,这是一个只读数据。你也不能修改。例如,在这种情况下ptr[0] = 'T'是不可能的。文本段中的字符串文字(3个字节)将在整个过程的生命周期中存在。但是一旦控件来自函数func,则将释放为变量ptr分配的4个字节以保存字符串文字的地址。你也可以写下你的函数func,如下所示

char* func()
{
    return "OK";
}

更改您的功能,如下所示

char* func()
{
    char ptr[] = "OK";
    return ptr;
}

这次将为变量ptr分配3个字节以在本地存储字符串。这个范围只在函数内。

答案 7 :(得分:0)

堆栈上的ptr本身是暂时的,但它指向的不是。一种情况就像在你的func()中,字符串文字存储在“常量数据区”中,另一种情况是数据在堆上分配,即通过malloc(),因此是全局的,并且在堆栈时不会被销毁功能消失了。

char* func()
{
        char* ptr;
        ptr = (char*)malloc(100);
        strcpy(ptr, "OK");
        return ptr;
}