【问题标题】:Why can I dereference a char pointer / string return value from a function?为什么我可以从函数中取消引用 char 指针/字符串返回值?
【发布时间】:2021-05-13 11:33:46
【问题描述】:

假设我有一个函数可以返回一个字符的指针,或者更具体地说是一个字符串:

char* fun_that_returns_string () {
    char* teststr = "Hello World";
    return teststr;
}

现在我调用该函数并将其返回值分配给其他地方的char*

char* s = fun_that_returns_string();

然后我可以打印返回的字符串并得到“正确”的结果:

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

输出:

> Hello World

本地值teststr或者它的地址不应该在函数外无效,因为它返回后被清除了吗?它是未定义的行为吗,我很幸运在打印之前没有被覆盖?如果是这样,处理返回字符串的正确方法是什么?

另一个例子:当我使用预定义的函数时,例如ctime(3) 来自 time.h,它返回一个 char*,我直接在另一个函数的参数中调用该函数

time_t t;
t = time(&t);

foo(ctime(&t));

这个函数将接收ctime()的返回值,它是一个指向时间字符串第一个字符的指针,作为一个副本。所以和上面的一样吗?我的理解是,ctime() 内部发生的任何事情都不应再被取消引用,除非它在堆上被 malloc'ed(但在这种情况下我必须自己释放它)?

我的教授在一些示例代码中使用了这个 ctime()-direct-argument-thing,但我无法理解它。

【问题讨论】:

标签: c


【解决方案1】:

您认为函数返回局部变量的地址通常是正确的,因为一旦函数结束,该变量将“不复存在”。但是,在您的代码中,您将返回字符串文字的地址。在这种情况下,C Standard 保证数据将具有静态存储:

6.4.5 字符串文字


语义

6    … 然后使用多字节字符序列来初始化一个静态存储持续时间和长度刚好足以包含该序列的数组。

关于ctime 函数返回的字符串的第二点,静态存储再次派上用场。 From cppreference:

返回值

  1. 指向以空字符结尾的静态字符串的指针,该字符串包含日期和时间的文本表示。该字符串可以在 asctime 和 ctime 之间共享,并且可以在每次调用这些函数时被覆盖。

有关 C 中使用的各种存储类(包括静态存储)的描述,here is a nice tutorial

【讨论】:

    【解决方案2】:

    您的第一个示例完全合法并且按预期工作。

    原因是您获取的是静态字符串的地址。 "Hello World" 定义了保存在程序二进制文件中的字符数组。然后它会在运行时向您返回该数组的地址。由于字符串是程序的一部分,它始终可用,并且它的指针永远不会变得无效。因此,定义字符串的函数是否返回与指针的有效性无关。

    【讨论】:

      猜你喜欢
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-06
      相关资源
      最近更新 更多