我为儿子编码了一个Arduino项目,并在此过程中学习了C语言。一切正常,但是将代码分成十个文件并将变量分组为每个文件的结构后,我无法解决一个问题。我们需要根据经验确定用于存储和平均端口读取数的数组的最佳大小,这就是我想要的:
struct Alarms {
// Configurable parameters
const unsigned int number_of_reads = 24;
// State variables
int reads[number_of_reads]; // Error: invalid use of non-static data member 'Alarms::num_of_reads'
};
这很简单,但是不起作用。我尝试了灵活的数组成员,直到发现C ++不支持该功能。 Arduino使用C ++进行编译。我尝试了许多“结构黑客”的例子,但它们都返回了如下错误:
struct Alarms {
// Configurable parameters
int number_of_reads = 24;
// State variables
int reads[];
} ar;
void setup_alarm() {
ar.reads = malloc(sizeof(int) * ar.number_of_reads); // Error: incompatible types in assignment of 'void*' to 'int [0]'
}
那看起来很有希望,但我怀疑我的无知正在明亮地发光。大多数struct hack示例都要求声明该struct,然后初始化struct变量。我希望不重复该结构。
我考虑过拆分结构,但这很容易出错,并且很可能是另一个编译错误:
struct Alarms2 {
int reads[ar.num_of_reads]; // Error: array bound is not an integer constant before ']' token
} ar2;
另一种方法是调整数组大小,然后再获取大小,但需要说明:
struct Alarms {
// Configurable parameters
int reads[ 24 ]; // Put number of reads to average between brackets
// State variables
int number_of_reads;
};
void setup_alarm() {
ar.number_of_reads = sizeof(ar.reads) / sizeof(ar.reads[0]); // this works
}
有没有一种方法可以处理struct hack或Arduino中的一些类似解决方案来实现第一个示例?
答案 0 :(得分:0)
在编译时必须知道结构的大小。结构中的常量数据类型可以随结构的每个实例而变化,这就是为什么在尝试初始化数组时会无效使用非静态数据成员'Alarms :: num_of_reads'的原因。解决此问题的最佳方法是拥有一个init_alarm
和destroy_alarm
函数。像这样...
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_NUM_OF_READS (24)
struct alarm {
// Configurable parameters
const int number_of_reads;
// State variables
int *reads;
};
void init_alarm(struct alarm *alarm)
{
alarm->reads = (int *) malloc(alarm->number_of_reads * sizeof(int));
}
void destroy_alarm(struct alarm *alarm)
{
free(alarm->reads);
}
int main(int argc, char **argv)
{
// When we create our struct, set number_of_reads to default
struct alarm alarm = {.number_of_reads = DEFAULT_NUM_OF_READS, .reads = NULL};
init_alarm(&alarm);
alarm.reads[0] = 13;
alarm.reads[23] = 100;
printf("alarm.reads[0] = %d, alarm.reads[23] = %d\n", alarm.reads[0], alarm.reads[23]);
destroy_alarm(&alarm);
return 0;
}
注意:为了使用指定的初始值设定项来初始化结构,您必须像这样使用ANSI(C99)进行编译...
gcc --std=c99 test.c -o test