【问题标题】:How to initialize static pointer with malloc in C?如何在 C 中使用 malloc 初始化静态指针?
【发布时间】:2013-05-19 10:54:53
【问题描述】:

我正在尝试在 C 中使用 malloc 启动一个静态变量(在函数内部),但我得到了“初始化程序不是常量错误”。我知道我无法在 C 中使用非常量启动静态,但有人能想到解决方案吗?我需要代码具有与此相同的效果:

static int *p = (int *)malloc(sizeof(int));

有什么技巧/解决方法吗?

编辑:我有一个函数,每次标志变高时都会调用它。在这个函数中,我正在创建并启动一个新线程。我声明一个指向结构的指针并使用 malloc 分配内存,然后将此指针传递给线程。然后函数返回控制。当我重新进入函数时,我最初打开的线程仍然在运行,我希望能够访问我最初传递给线程的内存区域。这就是为什么我需要一个静态的,这样我就可以在第一次调用时进行 malloc,然后在后续调用中使用相同的地址。这样我就可以从线程中获取信息。所有这些都是为了避免使用全局变量。

【问题讨论】:

    标签: c static malloc constants initializer


    【解决方案1】:
    static int *p = NULL;
    if(!p) p = (int *)malloc(sizeof(int));
    

    【讨论】:

    • 这不需要两个变量,因此比公认的答案更好。
    • @JonathanLeffler 我同意,尽管我的回答仍然很有价值,因为它更通用 - 适用于没有指定空值的情况。
    【解决方案2】:

    假设您想要函数静态变量:

    int foo(void) {
        static int b=1;
        static int *p;
        if (b) {
            p =  malloc(sizeof(int));
            b = 0;
        }
        ...
    }
    

    只要您知道第一次调用后它永远不会是NULL,您就可以对 p 使用 NULL 值作为检查。

    记得检查malloc中的错误;这是一个运行时分配,当不再需要它时也应该被释放。

    【讨论】:

    • 感谢您的解决方案!基本上我试图做的是让 malloc 分配一次并为后续调用保留相同的地址。这正是这样做的。
    • 这将如何编译?那个“if...”必须放在像 main() 这样的函数中,在这种情况下你有普通的运行时分配。
    • @LeeDanielCrocker - 我认为这是在函数内部。是的,当然这是一个普通的运行时分配——这就是 OP 所要求的。
    • 听起来你说的是函数内部的静态声明。你原来的问题没有这么说;您询问了文件级静态。是的,这个答案适用于函数内部声明的静态变量。
    • 是的,你碰巧假设了 OP 没有说的话,所以你做对了。愚蠢的我,回答实际提出的问题。 :-)
    【解决方案3】:

    malloc() 仅用于在运行时分配内存。静态变量在 Sompile 时初始化。你想要:

    static int p[1];
    

    【讨论】:

    • 如果您希望分配依赖于第一次调用的参数,这将无济于事。 VLA 可能会有所帮助,但我不知道具体如何。
    • 那么你真的是在运行时分配,你需要malloc(),而不是初始化器。这是两个不同的东西。
    • 是的,但这正是 OP 所要求的:在运行时只为静态变量分配一次。
    【解决方案4】:

    如果它是静态文件,那么您应该在该文件中提供一个公共函数来初始化该静态文件。

    void initialize () {
        if (p == 0) p = malloc(sizeof(*p));
    }
    

    或者,您可以使用静态函数代替静态变量。不过,每次访问都要花一张支票:

    static int * p () {
        static int * p_;
        return p_ ? p_ : (p_ = malloc(sizeof(*p_)));
    }
    

    对于整数类型,这似乎有点傻,但如果p 是一些更复杂的类型,需要更复杂的初始化序列,而不仅仅是malloc() 的返回值,那么有类似的东西可能是有意义的这个。

    【讨论】:

      【解决方案5】:

      C 做不到。 C++ 可以使用静态构造函数。

      您可以首先在 main() 中进行分配,或者在需要指针之前调用的任何其他函数中进行分配。

      虽然不可移植,但某些可执行格式(例如 Classic Mac OS 的代码片段管理器)支持初始化/终止入口点。 CFM 初始化用于 C++ 静态构造。如果您平台上的可执行格式支持初始化入口点,您可以使用它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-24
        • 2013-12-08
        • 2017-08-26
        • 2010-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多