Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在这种情况下如何避免全局变量(嵌入式C)_C_Global Variables_Mikroc - Fatal编程技术网

在这种情况下如何避免全局变量(嵌入式C)

在这种情况下如何避免全局变量(嵌入式C),c,global-variables,mikroc,C,Global Variables,Mikroc,我还在学习C语言在微处理器中的应用。一开始我用了很多globals。现在我正在尽可能地避免它,但对我来说,这并不总是清楚如何做到这一点 例如,电池监视器,在这种情况下,有4个函数需要读取或修改变量。 我有这些功能都使用可变低电压 void Check_Voltage(){ checks current voltage against LowVoltage } void Menu_Voltage(){ a menu on the LCD screen to set the value o

我还在学习C语言在微处理器中的应用。一开始我用了很多globals。现在我正在尽可能地避免它,但对我来说,这并不总是清楚如何做到这一点

例如,电池监视器,在这种情况下,有4个函数需要读取或修改变量。 我有这些功能都使用可变低电压

void Check_Voltage(){
  checks current voltage against LowVoltage
}

void Menu_Voltage(){
  a menu on the LCD screen to set the value of LowVoltage
}

void Save_LowVoltage(){
 runs after the settings menu is finished to save LowVoltage to EEPROM
}

void Load_LowVoltage(){
 reads EEPROM and sets LowVoltage at startup 
}
  • 检查_Voltage()并保存_LowVoltage()需要读取低电压
  • Load_LowVoltage()需要写入低电压
  • 菜单_Voltage()需要读取和写入低电压
我怎样才能在不使低电压全球化的情况下实现这一点?? 我是否需要制作另一个函数来读取或写入低电压? 大概是这样的:

unsigned int Low_Voltage(short Get, unsigned int Value){
  static unsigned int LowVoltage;

  if(Get) return LowVoltage;
  else LowVoltage= Value;
}
还是有更好的方法?我想一定有:)
最近我一直在阅读有关结构的文章,但说实话,我并不完全理解它们,我甚至不确定在这种情况下它是否会对我有所帮助?

在函数之间共享变量有几种选择:

  • 在静态内存中分配变量——这与代码所做的差不多。有两种选择:函数静态、转换单元静态和全局
  • 将指向变量的指针作为函数参数传递-此选项要求以某种形式传递指针
  • 通过智能初始化使用线程本地存储-使用微控制器时,此选项通常不可用;为了完整起见,我把它列在这里
在您的情况下,我认为使用translation unit静态变量是合适的。将四个函数的实现放在一个C文件中,并将顶部的
LowVoltage
声明为静态变量:

static unsigned int LowVoltage;
这种简单但高效的封装机制为您提供了使用全局变量的所有好处,而没有使用全局变量的缺点:

static unsigned int LowVoltage;
  • C模块中的所有函数都可以“看到”这个变量,并且可以自由地操作它
  • C模块之外的任何其他函数都无法访问此变量。他们可以声明自己的
    LowVoltage
    变量,赋予它完全不同的含义

    • 我能想到的两种解决方案

    • 让函数签名像这样

      unsigned int Load_LowVoltage(unsigned int lowVoltage);
      
      LowVoltage = Load_LowVoltage(LowVoltage);
      
      void LowVoltage(unsigned int *lowVoltage)
       {
          *lowVoltage = modifiedValue;
       }
      
      Load_LowVoltage(&LowVoltage);
      
      然后传递
      低电压
      并为其指定返回值,如下所示

      unsigned int Load_LowVoltage(unsigned int lowVoltage);
      
      LowVoltage = Load_LowVoltage(LowVoltage);
      
      void LowVoltage(unsigned int *lowVoltage)
       {
          *lowVoltage = modifiedValue;
       }
      
      Load_LowVoltage(&LowVoltage);
      
    • 在函数中修改
      LowVoltage
      ,并像这样传递指向原始
      LowVoltage
      的指针

      unsigned int Load_LowVoltage(unsigned int lowVoltage);
      
      LowVoltage = Load_LowVoltage(LowVoltage);
      
      void LowVoltage(unsigned int *lowVoltage)
       {
          *lowVoltage = modifiedValue;
       }
      
      Load_LowVoltage(&LowVoltage);
      
      那么你可以这样使用它

      unsigned int Load_LowVoltage(unsigned int lowVoltage);
      
      LowVoltage = Load_LowVoltage(LowVoltage);
      
      void LowVoltage(unsigned int *lowVoltage)
       {
          *lowVoltage = modifiedValue;
       }
      
      Load_LowVoltage(&LowVoltage);
      

    • 我认为第二个解决方案更清洁,因为你身处资源有限的联合国环境中,从这个意义上讲也更好。但是它们都很容易实现,并且工作正常。

      您可以创建一个包含所有电池参数的结构,例如:

      typedef struct {
        int low_voltage; 
        int voltage;
        int capacity;
        int temperature;
        ...
      } BatteryData
      
      void Load_LowVoltage(BatteryData *battery){
       //reads EEPROM and sets LowVoltage at startup 
       int eeprom_val = get_low_voltage_from_eeprom();
       battery->low_voltage = eeprom_val;
      }
      
      在程序开始时,为其分配内存,并将成员初始化为某些起始值:

      BatteryData *battery = malloc(sizeof(BatteryData));
      battery->low_voltage = 0;
      ...
      
      然后将指向整个结构的指针传递给设置或读取单个值的函数,例如:

      typedef struct {
        int low_voltage; 
        int voltage;
        int capacity;
        int temperature;
        ...
      } BatteryData
      
      void Load_LowVoltage(BatteryData *battery){
       //reads EEPROM and sets LowVoltage at startup 
       int eeprom_val = get_low_voltage_from_eeprom();
       battery->low_voltage = eeprom_val;
      }
      
      在不需要时释放结构:

      free(battery);
      

      这些函数是同时使用的吗?不要将“全局变量”(即暴露于整个程序的文件范围变量)与仅对放入它们的文件可见的私有文件范围变量混淆。前者是非常糟糕的实践,永远不应该使用,后者大多数时候是很好的编程实践。@moffeltje,不,它们从来没有同时使用过。但这并没有提供私有封装。很明显,他正在编写某种“电池”驱动程序,而打电话的人不应该关心该驱动程序的内部结构,这个低电压变量似乎是什么。将其设为静态文件范围变量,并将所有这些函数放在一个battery.h/battery.c代码模块中,这似乎正是OP需要做的。谢谢dasblinkenlight!这确实是我所想的,但当我在两个不同的C模块中有相同的静态变量名时,它们不知何故在同一范围内。因为直到最近我才了解静态变量及其作用域,所以我认为我误解了它。但现在我开始明白为什么我经常看到对米克罗克的抱怨。。。我已经将.c文件包含在#include中,如果我将.c文件包含在项目经理那里,它会正常工作……我认为这是个坏主意。在嵌入式系统上最好避免使用动态分配。如果您必须使用它,那么只需为它分配一次内存,而不要释放它。根据具体情况,多次释放和重新创建分配将很快导致堆损坏。