2016-02-17 25 views
3

我正在写一个数据混搭函数,我正在修改一些动态位压碎机音频过滤器的音频数据。对我来说使用静态变量很方便,因为它们的值在函数调用之间传递,这有助于通过在渲染回调中增加等来实现一些有趣的基于时间的效果。让静态函数变量取参数值C

例如,一种效果使用sin函数随时间调制一些声音效果。像这样:

void mangle(float * data, int n) { 

    static bool direction = false; 

    static float bottom = 0; 
    static float top = n; 
    static float theta = 0; 

    theta += 5; 

// data = sin(theta) etc.. 

所以,我希望theta进行一次初始化,并且比随时间修改。同样,顶部想成为静态变量,因为我稍后在函数中修改它。另外,top应该取参数n的值,因为n根据程序状态而改变。但是,当我去分配ntop,我得到的编译器错误

Initializer element is not a compile-time constsant

有没有办法给静态变量赋一个参数?有没有另外一种方法来实现我想要的静态变量?我知道我可以使用实例变量,但我觉得太多了。

+0

听起来不错,只要你明白你的过滤器不是线程安全的。 –

回答

1

在你的情况, top本地静态变量

它像全局静态变量和全局变量,他们都有静态存储时间,他们有代码启动前值。

的原因,你有类似这种情况下错误:

int a; 
int b = a; \\initializer is not a constant 

int main() { 
... 
} 

随着你的目的,使用top作为全局变量是要走正道。

+0

所以'静态'方面在这里其实并不重要? –

5

static变量是初始化在程序执行开始之前,因此您不能使用变量值来初始化一个static变量。你需要一个编译时常量来初始化变量static

引用C11标准,章第6.2.4节,对象的存储持续时间(重点矿山

[..]或与存储类 符静态的,具有静态存储持续时间。它的使用期限是 程序的全部执行和其存储值在程序启动之前仅初始化一次。

但是,你总是可以分配一个新值static变量。

这就是说,来到初始化部分,按章§6.7.9,

如果具有静态或线程存储时限的对象没有初始化 明确,然后
- 。 ..
- 如果有算术类型,它被初始化为(正或签名)零
- ...

因此,您不需要初始化static float明确0。您可以在代码后面分配任何值。

1

你应该做的是创建一个结构,该结构保存跨越调用所需的数据并将指向结构的指针传递给该函数。如果你wnat获得幻想,您可以创建函数分配,初始化和自由这样的结构(和永远不需要知道该结构的内容是功能的用户

喜欢的东西:

struct mangle_t { 
    bool direction; 
    float bottom; 
    float top; 
    float theta; 
}; 

struct mangle_t* mangle_open(void) 
{ 
    struct mangle_t* m = malloc(sizeof *m); 

    if (m) { 
     memset(m, 0, sizeof *m); 
    } 

    return m; 
} 

void mangle_close(struct mangle_t* m) 
{ 
    free(m); 
} 



void mangle(struct mangle_t* m, float * data, int n) { 

    m->top = n; 
    m->theta += 5; 

} 

至于分配参数到一个静态变量,你可以perofrm分配任何其他变量(但不是在变量的声明初始化 - 只会发生一次)。

+0

所以我实际上能够通过执行'static float top;'然后'top = n'来获得我想要的行为。这使我获得了所有持久状态,这使我可以执行基于时间的操作,而不需要构造或额外的复杂性。调用者总是只传递n的值。 –

+0

是的 - 为静态使用static比较容易,但不能缩放 - 它们有很多与全局变量相同的问题。如果你的需求很简单,那么使用静态可能就足够了。我并不是说你需要摆脱当前实现的静态变量,但是当你想要使用静态变量来保持持久化上下文时,请记住这一技巧,因为当你的应用程序变得更复杂时,它可能是解决方案(例如因为需要同时处理多个音频流或某物)。 –

+0

另外请记住,你不一定需要去完全打开/关闭或init/free函数的复杂性 - 这些只是提供隐藏数据和实现细节的机制。通常这是可取的,但是您的具体可以优先考虑。调用者管理所有权和初始化的情况下,您总是可以拥有一个结构体(或变量,如果持久状态是最小的话)。 –

1

我不知道,如果你想一次初始化top,然后继续使用,但是如果是这样,这是我会做什么:

void mangle(float *data, int n) { 
    static float top = -1; // Assuming that n will never be -1 
    if (top == -1) 
     top = n; 
    // ..... 
} 

如果您不需要保留的价值top通过函数调用,不需要声明它static