【问题标题】:Using global multidimensional arrays使用全局多维数组
【发布时间】:2020-10-15 20:54:42
【问题描述】:

我目前正在开发一个基于 Atmega2560 的硬件项目,并且我已经编写了大约 2000 行 C++ 代码 - 现在变得难以管理。这是一个本地社区的项目,可维护性很重要,所以我试图将所有内容都提取到模块中并保持简单,这样即使我对 C++ 了解更少的人至少也能理解正在发生的事情。

项目的核心是一个全局多维整数数组,最初在 main.cpp 中声明(它与 main.cpp 中包含的所有函数都可以正常工作):

// main.cpp
const int A = 30;
const int B = 20;
const int C = 10;
int gArray[A][B][C];

如果我在 GLOBAL.h 中做同样的事情,它编译得很好 - 所以,很明显,A、B 和 C 被接受为常量。但它不适用于跨模块。如果在我使用的代码模块中:

// setup.cpp
extern const int A;
extern const int B;
extern const int C;

extern int gArray[A][B][C];

我得到“数组绑定在 ']' 标记之前不是整数常量”错误。

所以我的问题基本上是 - 我如何在多个模块中使用全局多维数组,并将固定维度设置在一个地方以实现可维护性?

我一直在尝试让一些人对此进行排序,阅读并尝试了很多我读过的想法,但我无法取得任何进展。与此同时,我创建了设置和读取数组值的函数,并将它们放在 GLOBALS.h 中——这看起来不太优雅,但却是一种可以理解且实用的解决方法:

const int A=30;
const int B=20;
const int C=10;

int gARRAY[A][B][C];

void setARRAY(int A, int B, int C, int V) {
    gARRAY[A][B][C] = V;   
}

int getARRAY(int A, int B, int C) {    
    return gARRAY[A][B][C];
}

【问题讨论】:

  • 您必须将extern 添加到所有文件中的 const 变量中。在哪里声明它们以及在哪里使用它们。
  • @EmmanuelMathi-Amorim 我不确定仅此一项是否可行。编译器抱怨,因为它没有 A、B、C 的值,其中数组被声明为 extern
  • @Anonymous1847 我明白你的意思。 OP 可能应该将 const 变量切换为宏定义,或者如果它们有 C++ constexpr 可用,那么这是最好的。

标签: arrays arduino global arduino-c++


【解决方案1】:

解决了!!!

首先,过失 - 在使用 gArray[30][20][10] 遵循建议时,我没有注意到我超出了 RAM 容量!因此,当我可能拥有应该是一种工作方法时,处理器崩溃了[没有编译器警告]。现实是我其实只需要gArray[10][13][10]

修复此问题并使用来自 kind cmets 的提示使其工作的结果。

如果其他人需要使用全局多维数组,这就是我的做法[注意我使用的是 Arduino 环境,因此没有 int main() 例如]:

首先,在GLOBALS.h 中设置维度#defines,然后在GLOBALS.cpp 中声明数组:

// --- GLOBALS.h -------------------------
#ifndef GLOBALS_H
#define GLOBALS_H

    #define A 10
    #define B 13
    #define C 10

#endif

// --- GLOBALS.cpp -----------------------------
#include "GLOBALS.h"

int gArray[A][B][C];

然后我创建了几个测试模块setup.h & setup.cpp 来初始化数组值和testaccess.h & testaccess.cpp 来更改值,以及main.cpp 来测试它[包含Arduino void setup()void loop(),后者没有显示,因为它是空的]:

//--- setup.h ---------------
void loadArray();

//--- setup.cpp -------------
#include "GLOBALS.h"

extern int gArray[A][B][C];

void loadArray() {

    // set up some arbitrary test values
    gArray[1][1][1] = 99;
    gArray[1][13][1] = 13;
}

testaccess.h & testaccess.cpp我修改了两个测试值:

// --- testaccess.h -------------------------
int testArray();

// --- testaccess.cpp -----------------------
#include "GLOBALS.h"

extern int gArray[A][B][C];

void testArray() {
    gArray[1][1][1] = 9900;
    gArray[1][13][1] = 1300;
}

最后,在我的主代码中我做了测试:


#include <Arduino.h>
#include "GLOBALS.h"
#include "setup.h"
#include "testaccess.h"


extern int gArray[A][B][C];

void setup() {
  Serial.begin(9600);
  // set the test values
  loadArray();
  
  // and print them to the serial port to view
  Serial.println(gArray[1][1][1]);   //should be 99
  Serial.println(gArray[1][13][1]);  //should be 13
  Serial.println("----------");

  // now modify one of the values and print it:
  gArray[1][13][1] += 10;
  Serial.println(gArray[1][13][1]);  // should be 23
  Serial.println("----------");

  // and now modify both values in a different module
  testArray();
  Serial.println(gArray[1][1][1]);   // should be 9900
  Serial.println(gArray[1][13][1]);  // should be 1300
}

...串口上的结果是...

99        
13        
----------
23        
----------
9900      
1300  

经过两周的挣扎,我现在可以继续前进了!

感谢大家的帮助和启发。

【讨论】:

    【解决方案2】:

    不要在头文件中声明没有extern 的非常量全局数组。每次包含头文件时,都会重新声明并重新分配全局变量,这可能会导致链接器错误。在头文件中使用extern 声明全局变量,而在一个源文件中不使用extern。我相信 A、B、C 是这个规则的例外,因为它们是整数常量。我会这样做:

    GLOBAL.h

    const int A = 30;
    const int B = 20;
    const int C = 10;
    
    extern int gArray[A][B][C];
    

    GLOBAL.cpp

    #include "GLOBAL.h"
    int gArray[A][B][C];
    

    在您需要访问gArray 的任何地方包括GLOBAL.h。

    【讨论】:

      【解决方案3】:

      问题出在你写的时候

      int gArray[A][B][C];
      

      编译器需要知道常量ABC的值,因为编译器需要为gArray分配相应的内存。由于您声明常量是外部的,因此它对编译器没有帮助,因为当您链接到已知 ABC 的不同版本的目标文件时,它们可能会发生变化。

      作为一个建议,保留

      const int A=30;
      const int B=20;
      const int C=10;
      extern int gARRAY[A][B][C]; /* declares gARRAY but does not allocate memory for it */
      

      然后放

      #include "GLOBALS.h"
      int gArray[A][B][C]; /* allocates memory for gArray */
      

      放入您的一个实施文件(例如,setup.cpp)。否则,如果GLOBALS.h 包含在多个实现文件中,您将遇到麻烦。在这种情况下,链接器会抱怨 gARRAY 已被多次定义(在包含 GLOBALS.h 的每个编译单元中定义一次)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-23
        • 2012-06-07
        • 1970-01-01
        • 2021-12-30
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多