试图理解指针返回类型的工作原理

10 c++ pointers return-type return-value

我试图了解如何在以下场景中返回指针:

#include <iostream>
using namespace std;

// Why does this work? I can even pass the return value to another function
// and the contents do not change.
char* StringFromFunction()
{
  char* pReturn = "This string was created in the function.";
  return pReturn;
}

// I know this is wrong because the memory address where 5 is stored can be
// overwritten.
int* IntegerFromFunction()
{
  int returnValue = 5;
  return &returnValue;
}

int main()
{
  int*  pInteger;
  char* pString;

  pString = StringFromFunction();
  pInteger = IntegerFromFunction();

  cout << *pInteger << endl << pString << endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序输出正如我所期望的那样:

5
This string was created in the function.
Run Code Online (Sandbox Code Playgroud)

我在Visual C++ 2010 Express中获得的唯一编译器警告是" c:\ vc2010projects\test\main.cpp(14):警告C4172:返回本地变量或临时的地址 ",它仅显示我何时使用IntegerFromFunction()而不是StringFromFunction().

我认为我从上面的例子中理解的是以下内容:

在里面StringFromFunction(),文本的内存分配"这个字符串是在函数中创建的".在执行时发生,因为它是一个字符串文字,即使在函数返回后内容仍然存在于内存中,这就是为什么指针pStringin main()可以传递给另一个函数并且字符串可以显示在其中.

但是,对于IntegerFromFunction(),当函数返回时,现在释放分配的内存,因此可以覆盖该内存地址.

我想我的主要问题是,在整个程序中是否可以安全地传递指向字符串文字的指针?

Web*_*ter 3

查看差异的最简单方法是生成一个简单的 hello-world-ish 示例的反汇编:

char* test() {
 return "Test";
}

int main(int argc, char* argv[]) {
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是 FreeBSD 中 gcc 的反汇编,优化关闭

    .file   "hellow.c"
    .section    .rodata
.LC0:
    .string "test"
    .text
    .p2align 4,,15
.globl test
    .type   test, @function
test:
    pushl   %ebp
    movl    %esp, %ebp
    movl    $.LC0, %eax
    popl    %ebp
    ret
    .size   test, .-test
    .p2align 4,,15
.globl main
    .type   main, @function
main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    call    test
    movl    $0, %eax
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
    .size   main, .-main
    .ident  "GCC: (GNU) 4.2.1 20070719  [FreeBSD]"
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,字符串文字本身存储在 .LC0 部分中,而不是代码本身中。测试函数仅返回指向 .LC0 开头的指针(movl $.LC0, %eax),因为这是第一个字符串文字。该位置相似(但不相同),具体取决于您要编译到的可执行格式。读取A.out(文本段)或PE