使用全局多维数组
Using global multidimensional arrays
我目前正在从事一个基于 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];
}
不要在头文件中声明 non-const 没有 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。
问题出在你写的时候
int gArray[A][B][C];
编译器需要知道常量A
、B
和C
的值,因为编译器需要为gArray分配相应的内存。由于您声明常量是外部常量,因此它对编译器没有帮助,因为当您 link 到目标文件的不同版本时它们可能会更改,其中 A
、B
和 C
众所周知。
作为一个建议,保留
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
被多个实现文件包含,您将 运行 陷入困境。在那种情况下,linker 会抱怨 gARRAY
已定义多次(在包含 GLOBALS.h
的每个编译单元中定义一次)。
已解决!!!
首先,我认错了 - 在遵循使用 gArray[30][20][10]
的建议时,我没有注意到我已经超出了 RAM 容量!!所以,当我可能有什么应该是一个工作方法时,处理器崩溃了[没有编译器警告]。现实是我其实只需要gArray[10][13][10]
修复此问题并使用善意评论中的提示的结果使其有效。
万一其他人需要使用全局多维数组,我是这样做的[注意我使用的是 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
经过两周的挣扎,我现在可以继续前进了!
感谢大家的帮助和启发。
我目前正在从事一个基于 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];
}
不要在头文件中声明 non-const 没有 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。
问题出在你写的时候
int gArray[A][B][C];
编译器需要知道常量A
、B
和C
的值,因为编译器需要为gArray分配相应的内存。由于您声明常量是外部常量,因此它对编译器没有帮助,因为当您 link 到目标文件的不同版本时它们可能会更改,其中 A
、B
和 C
众所周知。
作为一个建议,保留
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
被多个实现文件包含,您将 运行 陷入困境。在那种情况下,linker 会抱怨 gARRAY
已定义多次(在包含 GLOBALS.h
的每个编译单元中定义一次)。
已解决!!!
首先,我认错了 - 在遵循使用 gArray[30][20][10]
的建议时,我没有注意到我已经超出了 RAM 容量!!所以,当我可能有什么应该是一个工作方法时,处理器崩溃了[没有编译器警告]。现实是我其实只需要gArray[10][13][10]
修复此问题并使用善意评论中的提示的结果使其有效。
万一其他人需要使用全局多维数组,我是这样做的[注意我使用的是 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
经过两周的挣扎,我现在可以继续前进了!
感谢大家的帮助和启发。