函数中的静态变量

时间:2011-07-09 17:26:27

标签: c

在函数计算中是否存在使用静态变量的性能问题,是否会影响函数执行的速度,因为静态变量只初始化一次?

问题是高度重复的呼叫优化。

考虑这个例子

int calcme(int a, int b)
{
 static int iamstatic = 20;
 return a*iamstatic + b;
}

使用static的原因是希望,每次调用函数时,iamstatic都不会被置于堆栈中,并且如果需要,它将被设计为更改。 (省略静态变量代码)

8 个答案:

答案 0 :(得分:8)

我认为你可能会降低性能。使用静态时,内存位于程序的bss部分。当调用该函数时,它访问两个不同的位置,即函数存储器和参数存储器。如果它是本地的,那么你可能会因本地化而获得性能,当所有参数都在同一个缓存行时,也就是当cpu读取内存时它读取一个完整的缓存行(16个字节是一个常见的行大小),你读全部一个内存中的数据访问缓存。

答案 1 :(得分:3)

是。在你的例子中,它可能没有帮助(至少足以关心)。事实上,它甚至可能会有点伤害,因为它可能涉及从内存加载数据,而本地可能只涉及将值加载到寄存器中。如果初始化足够慢以使性能变得重要,那么只要初始化一次是可接受的,使变量static可以提高性能。

答案 2 :(得分:2)

答案在技术上是“否”,因为C标准没有指定它。

效率取决于许多因素,如变量使用和硬件。如果您愿意,您可以编写多次调用的变量函数,以测试差异。在实践中,可能存在非常小且无关紧要的差异。

答案 3 :(得分:1)

这是该功能最具可读性和最高性能的版本。

int calcme(int a, int b)
{
    return a*20 + b;
}

如果在static变量中放置常量,编译器可能会发现它永远不会更改,并将其转换为立即数操作数。也许编译器不会弄清楚它会从内存中加载静态。

如果在全局变量中放置常量,编译器将从内存中加载变量。

你试图超越优化器,这几乎总是一个坏主意。

这是您的原始代码,已编译:

    leal    (%rdi,%rdi,4), %edi
    leal    (%rsi,%rdi,4), %eax
    ret

这与return a*20 + b;生成的代码相同,但您的代码更难以阅读。请注意,静态变量实际上并未存储在任何位置,它会转换为立即操作数(然后强度降低会进一步降低它)。您将从以下代码获得相同的性能:

int calcme(int a, int b)
{
    int local = 20; // "initialized" every time the function is called
                    // yet the assembly is the same
    return a*local + b;
}

答案 4 :(得分:0)

我不会立即看到任何使用静态变量的性能提升或惩罚。

您可以做的是反汇编两个相同的函数并比较代码或分析每个函数。

答案 5 :(得分:0)

你为什么不做一个简单的

#define MY_CONSTANT 20

/* ... */

return a*MY_CONSTANT + b;

也许编译器知道一个技巧乘以20(当你乘以iamstatic时它将无法应用。)

答案 6 :(得分:0)

如果使用优化进行编译,则取决于具体情况。 在您的示例中,iamstatic是常量,我猜速度不会改变。

您应该尝试测量执行时间或查看汇编代码。

答案 7 :(得分:0)

接受的答案是正确的,但也许更重要的是,你不应该根据尝试使其“更快”来选择变量的存储持续时间,而是根据代码的正确语义来选择。

  1. 如果变量存储需要在函数调用期间保持的全局状态,则它应具有静态存储持续时间。 (通常这是有害的,但有时它是一个必要的邪恶,或者至少使事情变得更容易,你愿意犯下编写错误代码的罪行,以节省大量的开发时间/成本。)
  2. 如果变量存储特定于当前函数调用的数据,则它应具有自动存储持续时间(默认值)。
  3. 如果数据属于当前执行上下文但需要在函数返回后保留,则应将其存储在malloc获取的对象中。