如何实现:如果函数还没有被调用,做点啥?

Posted

技术标签:

【中文标题】如何实现:如果函数还没有被调用,做点啥?【英文标题】:How to implement: do something if the function hasn't been called yet?如何实现:如果函数还没有被调用,做点什么? 【发布时间】:2019-09-20 09:05:42 【问题描述】:

在 C 语言中有没有一种方法可以做到:如果一个函数之前在代码的前一部分中没有被调用过,那么就调用它,否则如果之前已经调用过,那么就不要调用它?

这里有一些代码:

while (function hasn't been called)

    // do some code

else (call the function)

    // do something else

类似的东西?

【问题讨论】:

// do some code 最终会调用该函数还是我们在这里查看并发代码? 该代码没有任何意义。也许while 本来是一个if。否则,您需要解释当代码卡在while 循环中时函数是如何被调用的(正如丹尼尔指出的那样)。 【参考方案1】:

嗯,这很容易。只需使用静态变量即可。

void foo() 
    static int hasBeenCalled = 0;
    if(!hasBeenCalled) 
        /* Do stuff */
        hasBeenCalled = 1;
    

您不必对全局变量和静态变量执行初始化,因为它们的默认值为 0,而局部变量则没有。但恕我直言,它看起来好多了。全局变量和静态变量很少使用,以至于我看不出使用这个“特性”的意义。

从技术上讲,您仍然使用上述方法调用该函数。如果这是一个问题,您可以使用全局变量并将我使用的逻辑放在外面。这是一个工作示例:

int hasBeenCalled = 0;

void foo() 
    while(!hasBeenCalled) 
        /* Do stuff that eventually calls bar() */
    


void bar() 
    hasBeenCalled=1;
    /* Do stuff */


int main() 
    foo();

【讨论】:

static int 有效,应该指出静态变量默认的初始值为 0,并且存储在 .data 部分中,而不是本地到堆栈中。它们没有什么神奇之处,就像使用全局变量一样。 @Nina 虽然你所说的都是真的,但我认为指出这一点没有意义。我总是初始化全局变量和静态变量,即使它们应该设置为零。 这种技术的唯一问题是代码是否可以从多个线程中使用。然后他们中的几个可能会立即进行初始化。 POSIX 提供了pthread_once() 来解决这个问题。对于 OP 来说,这可能还不是问题。【参考方案2】:

很遗憾,您用来说明意图的代码不是很清楚。但是,你确实问过这个:

...如果在前面的代码部分中没有调用过函数,则调用它,否则如果之前已调用过,则不要调用它?

除了使用布尔值,您还可以使用函数指针。函数指针指向第一次调用该函数时应调用的函数。然后,该函数将函数指针更改为指向第一次之后应该调用的函数。

static void foo_first_time(void);
static void foo_after_first_time(void);

void (*foo)(void) = foo_first_time;

static void foo_first_time(void) 
    foo = foo_after_first_time;
    // do some code
    // ...


static void foo_after_first_time(void) 
    // do something else
    // ...

现在,调用者只需正常调用foo()。第一次会调用foo_first_time,但后续调用会调用foo_after_first_time

int main () 
    foo(); // calls foo_first_time
    foo(); // calls foo_after_first_time
    foo(); // calls foo_after_first_time again

【讨论】:

以上是关于如何实现:如果函数还没有被调用,做点啥?的主要内容,如果未能解决你的问题,请参考以下文章

每 180 度后做点啥

如果 API 数据加载失败,那么做点啥

在 kivy 退出时做点啥

播放声音,等待它完成然后做点啥?

基类和子类函数名相同且参数类型一样,基类函数如何被覆盖,还存在吗?存在何处?请详细回答,谢谢~~~~

如何把一个接口的所有实现类反射出来?