代码之家  ›  专栏  ›  技术社区  ›  Cardstdani

参考与C中局部变量的工作效率

  •  0
  • Cardstdani  · 技术社区  · 1 年前

    我在C中定义了一个函数如下:

    char **fun(size_t *size) {  
      size_t local_size = 0;
      while (...) {
        //Function code...
        local_size++;
      }
      *size = local_size;
      //Code for returning
    }
    

    正如您所看到的,它有一个局部变量作为计数器,然后通过将大小引用的值设置为局部大小的值来返回它。

    此外,我通过直接使用输入引用所指向的值来实现该函数,如下所示:

    char **fun(size_t *size) {  
      *size = 0;
      while (...) {
        //Function code...
        (*size)++;
      }
      //Code for returning
    }
    

    假设它们有相同的行为,如果我知道函数内部会有很多对变量的访问,那么哪个选项更有效?使用局部变量选项来利用堆栈内存分配是否更快?

    2 回复  |  直到 1 年前
        1
  •  1
  •   ikegami Gilles Quénot    1 年前

    如果 //Function code... 包含任何可能访问的内容 size 指向,编译器无法通过缓存的副本进行优化 *size :

    • 如果它为可能使用别名的对象使用文件作用域标识符 size_t , 大小 可能指向那个对象。
    • 如果它调用编译器看不到或不知道其定义的任何其他函数,则该函数可能会访问 大小 .
    • 如果它从编译器不完全知道的地方获得一个字符指针,并使用该字符指针来修改内存,则可能会发生变化 大小 ,因为允许字符类型访问任何对象。
    • 示例函数没有其他参数,但实际函数通常有多个参数,这会引发相同的问题,即它们可能指向同一对象 大小 指向。

    因此,您最好使用该函数的第一个版本。

        2
  •  1
  •   Petr Skocik    1 年前

    从优化的角度来看,制作小型内存对象的本地副本通常也是一个好主意,因为它们可以帮助编译器解决混叠问题。

    编译器自然会通过在寄存器中缓存内容来尽可能避免内存访问,但有时编译器很难决定何时使缓存的值无效,因此必须保守地刷新/重新加载。 (其中一些可以通过使用严格的混叠或 restrict 限定符,但局部变量通常可以完成相同的工作)。

    写入内存位置也意味着,即使编译器设法使用寄存器来缓存这些写入,它最终也可能会被迫比通过局部变量手动缓存更快地刷新缓存,例如,不透明的函数调用或对具有不清楚混叠的内存的访问将强制这样的刷新。

    如果有疑问,请比较程序集输出。