C语言 - 没有使用malloc返回字符指针

7
请考虑以下代码:
char* pointerTesting(void) {

    char* test = "hello";
    return test;
}

int main() {

   char* string = pointerTesting();
   printf("string: %s\n", string);
}

这段代码在编译和运行时没有问题。但是,在我看来,这应该无法正常工作,因为指向 test 指针的内存位于堆栈中,并且返回到主函数时会被销毁。

那么问题来了,为什么在 pointerTesting() 函数中没有使用 malloc,也能够正常工作呢?


3
请参阅https://dev59.com/p3E85IYBdhLWcg3w1HKF以及Stackoverflow上关于此主题的一系列类似问题。 - jman
指针(pointer)通常在堆栈上分配,但您并没有返回指针,而是返回其值的副本。这类似于 int n = 42; return n;。重要的是它所指向的内容的分配。 - Keith Thompson
3个回答

16
在这种情况下,字符串"hello"存储在全局内存中。因此,它已经分配好了内存。
因此,在从函数返回时,它仍然是有效的。
但是,如果你这样做:
char test[] = "hello";
return test;

那么,不行,这将导致未定义的行为。在这种情况下,字符串实际上是一个本地数组 - 当函数返回时,该数组不再存在。

*虽然这通常是正确的,但标准并没有规定它必须存储在全局内存中。
但重要的是,字符串字面值的生命周期是整个程序的持续时间。(请参见注释)


如果你的回答提到"hello"是由于实现上的意外而在全局内存中,而不是由于任何标准规定的行为,那么我会更加高兴。 - sarnold
@sarnold同意,我应该将其更改为“通常存储在全局内存中”吗?还是应该说“存储在其他地方”? - Mysticial
我喜欢你现在的星号。:) 谢谢! - sarnold
4
标准没有使用术语“全局存储器”,我不确定其确切含义。标准要求与字符串字面值相对应的数组具有静态存储期,这意味着其生命周期为程序的整个执行过程。(术语“全局”通常指生命周期和可见性)。 - Keith Thompson
该网址https://dev59.com/p3E85IYBdhLWcg3w1HKF的答案(感谢@bowie-owens)也提供了一个很好的解释问题的方法(同时他们使用了程序的只读部分这个术语)。 - Fisher

6
您正在返回test,即字符串字面量"hello"中第一个字符的地址(与所有字符串字面量一样,以这种方式存储为char数组,以便在程序的生命周期内可用)。如果您试图返回test地址以供以后使用,则可能会遇到问题。

现在,以下代码片段将不起作用

char *pointerTesting(void)
{
  char test[] = "hello";
  return test;
}

在这种情况下,您正在尝试返回本地于函数的数组对象中第一个元素的地址,一旦函数退出,该地址将无效。请记住,在大多数情况下,“N个元素的T数组”的表达式将被替换为类型为“指向T的指针”的表达式,其值是数组中第一个元素的地址。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接