C: 根据函数调用位置的静态变量

huangapple go评论51阅读模式
英文:

C: Static variable depending on function invocation location

问题

在C程序中,可以通过使用函数指针和动态分配的内存来实现您所描述的功能。这样,您可以为每个函数调用位置维护一个不同的静态变量。以下是一个示例代码:

#include <stdio.h>
#include <stdlib.h>

// 定义一个结构体来存储静态变量和函数指针
struct StaticVariable {
    int sa;
    void (*func)(int);
};

// 初始化静态变量并关联到特定的函数
void initStaticVariable(struct StaticVariable *var, void (*func)(int)) {
    var->sa = 10;
    var->func = func;
}

// 函数foo
void foo(int increment) {
    static struct StaticVariable *sa_var;
    sa_var->func(increment);
}

// 打印函数
void printValue(int increment) {
    printf("increment = %d, sa = %d\n", increment, sa_var->sa);
}

int main() {
    int i;
    
    // 动态分配内存来存储不同函数调用位置的静态变量
    struct StaticVariable var1;
    struct StaticVariable var2;
    
    // 初始化这些静态变量并关联到特定的函数
    initStaticVariable(&var1, printValue);
    initStaticVariable(&var2, printValue);
    
    // 设置sa_var指针,用于在foo函数中访问正确的静态变量
    sa_var = &var1;
    
    for (i = 0; i < 5; ++i) {
        foo(1);
        sa_var = &var2;
        foo(2);
        sa_var = &var1;
    }
    
    return 0;
}

这个代码中,我们通过使用结构体和函数指针来关联静态变量和函数。每个静态变量都与一个特定的函数关联,并在需要时进行切换。这样,您可以在不同的函数调用位置维护不同的静态变量。希望这能帮助您实现您的需求。

英文:

Is there a way to have a static variable in a C program that not only "remembers" its last value, but also its last function invocation location, and keeps a different value for each invocation location?

I mean that when the function is invoked on multiple occasions in the main function, each invocation creates its own "instance" of the static variable, and it is treated seperatly from the other "instances".

So for example if I have this code:

#include &lt;stdio.h&gt;

void foo(int increment)
{
    static int sa = 10;

    sa += increment;

    printf(&quot;increment = %d, sa = %d\n&quot;, increment, sa);
}


int main()
{
    int i;

    for (i = 0; i &lt; 5; ++i) {
        foo(1);
        foo(2);
    }
}

The output will be

increment = 1, sa = 11
increment = 2, sa = 13
increment = 1, sa = 14
increment = 2, sa = 16
increment = 1, sa = 17
increment = 2, sa = 19
increment = 1, sa = 20
increment = 2, sa = 22
increment = 1, sa = 23
increment = 2, sa = 25

However, my desired output would be

increment = 1, sa = 11
increment = 2, sa = 12
increment = 1, sa = 12
increment = 2, sa = 14
increment = 1, sa = 13
increment = 2, sa = 16
increment = 1, sa = 14
increment = 2, sa = 18
increment = 1, sa = 15
increment = 2, sa = 20

In other words, I would like to have two "instances" of sa. One of them is incremented by 1 and the other one is incremented by 2 for every main loop iteration.

If this is not possible, I guess I will have to pass the incremented value from main() to foo() and back every time (or just increment it in main()). Or is there a 3rd way to do it?

Note that I would like to have a solution that works for any number of different function invocation locations.

Edit: Removed mismatch between for-loop iteration count and output line count.

答案1

得分: 4

函数的定义不依赖于它们被调用的位置。:)

至于你的问题,你可以在函数中使用两个静态变量,如下所示

void foo(int increment)
{
    static int i = 0;

    static int sa1 = 10;
    static int sa2 = 10;

    if ( i == 0 )
    {
        sa1 += increment;
        printf("increment = %d, sa = %d\n", increment, sa1);
    }
    else
    {
        sa2 += increment;
        printf("increment = %d, sa = %d\n", increment, sa2);
    }

    i ^= 1;
}
英文:

Definitions of functions do not depend on where they are called.:)

As for your problem you could use two static variables in the function the following way

void foo(int increment)
{
    static int i = 0;

    static int sa1 = 10;
    static int sa2 = 10;

    if ( i == 0 )
    {
        sa1 += increment;
        printf(&quot;increment = %d, sa = %d\n&quot;, increment, sa1);
    }
    else
    {
        sa2 += increment;
        printf(&quot;increment = %d, sa = %d\n&quot;, increment, sa2);
    }

    i ^= 1;
}

答案2

得分: 2

如果您需要任意数量的计数器,可以使用宏来创建单独且完全独立的计数器,将完全按照您的要求执行:

#define FOO( increment ) \
do \
{ \
    int localIncrement = ( increment ); \
    static int sa = 10; \
    sa += localIncrement; \
    printf("increment = %d, sa = %d\n", localIncrement, sa); \
} \
while ( 0 )

每次调用都会在代码中的那一点创建一个独立的计数器。并且可以使用 _Generic 来检查 increment 的类型并提高健壮性。

对于多线程代码,sa 可以是一个原子值,可以使用原子增量。

英文:

If you need an arbitrary number of counters, a macro can be used to create individual and completely separate counters that will do exactly as you want:

#define FOO( increment ) \
do \
{ \
    int localIncrement = ( increment ); \
    static int sa = 10; \
    sa += localIncrement; \
    printf(&quot;increment = %d, sa = %d\n&quot;, localIncrement, sa); \
} \
while ( 0 )

Every invocation would create a separate counter at that point in the code. And _Generic could be used check the type of increment and improve robustness.

For multithreaded code, sa could be an atomic value and an atomic increment could be used.

huangapple
  • 本文由 发表于 2023年7月4日 20:16:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76612519.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定