Arduino / C ++ GlobalVars vs局部变量

时间:2016-05-20 09:48:17

标签: c++ arduino global

我正在研究Arduino项目。它的作用基本上是这样的:

  1. 从PC读取串行数据
  2. 解析收到的数据
  3. 使用此数据在TFT屏幕上绘图。
  4. 我目前的方法大量使用全球变量。没有它们,我将不得不使用一些嵌套函数来传递3级深度的变量。这让我想到哪种方法在性能方面更好。以下是两个例子。

    首先是本地:

    void setup() {
      Serial.begin(9600);
      Serial.println(firstFunction(10));
    }
    
    int firstFunction(int val)
    {
      return secondFunction(val+1);
    }
    
    int secondFunction(val)
    {
      return thirdFunction(val+1);
    }
    
    int thirdFunction(val)
    {
      return val + 1;
    }
    

    全局:

    int x; //global var
    void setup() {
      Serial.begin(9600);
      firstFunction(10);
      Serial.println(x);
    }
    void firstFunction(int val)
    {
      x = val;
      x += 1;
      secondFunction();
    }
    void secondFunction()
    {
      x++;
      thirdFunction();
    }
    void thirdFunction(val)
    {
      x++;
    }
    

    在PC方面,使用全局变量通常不受欢迎。但我的理解是,主要是出于样式和可伸缩性的原因。

    你们的想法是什么?

3 个答案:

答案 0 :(得分:1)

在我看来,风格更适合本地方法,也适用于通常较小的Arduino程序。一旦你有很多全局变量,你可以在结构中将它们传递给函数。

在设置功能中特别有用,设置完成后内存不再被占用。在您的版本中,x在程序的生命周期内仍将占用4个字节。只需2k内存即可快速达到极限。

我会做这样的事情:

typedef struct {
  int a, b;
} entity_t;

void foo(entity_t *e) { foo2(e); foo3(e); /* do stuff */ }

void setup()
{
  entity_t e = { 1, 2};

  foo(&e);

  Serial.println(e.a);
  // automatic memory of e is released
}

答案 1 :(得分:1)

根据项目的复杂程度,任何一种方法都是可行的。

通过一堆函数调用将变量作为参数传递出来的一个注意事项是你的微芯片上的内存量非常有限。每个局部变量和每个函数参数都放在你的堆栈中,在你的情况下你在堆栈上多次有相同的变量,浪费你的记忆。根据μC的RAM量,一旦开始使用字符串和其他想要在运行时操作的较大结构,这可能会变得毛茸茸。

如果您注意到突然您的μC开始行为不端 - 崩溃,挂起,产生垃圾输出等 - 可能是您正在将堆栈下溢到堆中或反之亦然。如果您首先尝试避免不必要的变量副本,则不太可能成为问题。

当然,根据程序的工作方式,情况恰恰相反:如果必须有某种状态,则只需要在程序的某个部分跟踪,并且不要调用许多嵌套函数在那里,将它保存在通过的局部变量中可能更好,因为一旦从外部函数返回,变量将再次消失。

基本上,根本区别在于全局变量总是存在并且在程序运行的整个过程中占用空间,而局部变量只有在创建它们的函数返回时才会这样做 - 但函数参数就像局部变量一样。函数,因此将变量传递给另一个函数会创建第二个副本。所以,它总是有两面性的。

然而,随着复杂性的增加,我肯定会使用类 - 按职责划分 - 使用成员或静态变量和相应的方法,而不仅仅是一堆全局变量。

然后你仍然把事情很好地捆绑在一起,而不仅仅是在全球空间中松散地浮动,但你不是在浪费记忆。

答案 2 :(得分:0)

我认为添加引用不会增加任何开销;记住编译器并不依赖于将其实现为指针。如果所有内容都在同一个编译单元中,那么它可能会被优化掉。几乎可以肯定,如果函数太小,它就可以内联。

如果设计允许,则另一种可能性是使这些函数和变量成为同一类的成员。

但最终,封装主要存在,因此通过转移程序员团队可以在数月或数十年内维护复杂的项目。 如果这是一个只有你会看到的小代码,那么可能没有必要过分依赖良好实践。