1

以这种方式使用复合文字初始化指针是安全的,而且完全有可能?:

#include <stdio.h>
#include <string.h>

void numbers(int **p)
{
        *p = (int []){1, 2, 3};
}

void chars(char **p)
{
        *p = (char[]){'a','b','c'};
}

int main()
{
    int *n;
    char *ch;

    numbers(&n);
    chars(&ch);
    printf("%d %c %c\n", n[0], ch[0], ch[1]);
}

输出:

1 a b

我不明白它是如何工作的,它与带有局部变量的 init 指针不一样吗?

如果我尝试打印:

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

什么都没有打印。

4

2 回答 2

5

在函数内部声明的复合文字具有与其封闭块关联的自动存储持续时间 (C 2018 6.5.2.5 5),这意味着它的生命周期在块执行结束时结束。

在内部numbers*p = (int []){1, 2, 3};将复合文字的地址分配给*p. 返回时numbers,复合文字不再存在,并且指针无效。在此之后,使用指针的程序的行为是未定义的。程序可能会打印值,因为数据仍在内存中,或者程序可能会打印不同的值,因为内存已更改,或者程序可能会因为尝试访问不可访问的内存而陷入陷阱,或者程序的整个行为可能会发生变化以剧烈的方式,因为编译器优化将未定义的行为完全改变了。

于 2018-10-26T12:11:40.107 回答
3

这取决于复合文字的放置位置。

C17 6.5.2.5 §5

复合文字的值是由初始化列表初始化的未命名对象的值。如果复合文字出现在函数体之外,则该对象具有静态存储持续时间;否则,它具有与封闭块关联的自动存储持续时间。

也就是说,如果复合文字在本地范围内,它的工作方式与本地变量/数组完全一样,并且从函数返回指向它的指针是不安全的

但是,如果它是在文件范围内声明的,它就像任何其他具有静态存储持续时间的变量一样工作,您可以安全地返回指向它的指针。但是,这样做可能表明设计存在问题。此外,您还会在多线程应用程序中遇到常见的线程安全问题。

于 2018-10-26T13:01:52.093 回答