C数组大小取决于编译时已知的变量值



我正在做一个从电子计数器读取串行数据的库。根据您的合同,计数器可以传输多达105个不同的标签。因为这个库可以在轻量级和不强大的嵌入式系统(通常是arduino或esp8266)上,我试图将内存使用减少到最低限度。

为了读取每个标记,我的库有一个长度等于最大标记值长度的缓冲区(范围从2字节到94字节)。我希望我的库能够自动将缓冲区大小设置为正确的值,知道用户能够在其主文件中使用#define指令指示他想要的标记。

main.cpp

#define BASE
#define HCHP
#define OPTARIF
#include "LinkyTIC.h"
#include <SoftwareSerial.h>
SoftwareSerial LinkySerial(13, 15);
LinkyTIC linky(LinkySerial);
void setup() {
}
void loop() {
if(linky.read()){
int base = linky.GetBASE();
int hchp = linky.GetHCHP();
Serial.println(base);
Serial.println(hchp);
}
}

What I tried:

在我的头文件中,我使用了一个#ifdef链来保持最大长度,但是我得到了错误的变量"max_length"不能用作常量。我试图将值转换为常量,但它也不起作用。

header.h

uint8_t max_length = 8;
#ifdef ADCO
uint8_t max_length = max_length > 12 ? max_length : 12;
#endif
#ifdef OPTARIF
uint8_t max_length = max_length > 4 ? max_length : 4;
#endif
#ifdef ISOUSC
uint8_t max_length = max_length > 2 ? max_length : 2;
#endif
#ifdef BASE
uint8_t max_length = max_length > 9 ? max_length : 9;
#endif
...
class LinkyTIC {
public:
// unrelated stuff
private:
// unrelated stuff
char _buffer_tag[8];            // buffer for the tag name

>>>>    char _buffer_date[max_length];          // buffer for the (optional) tag date. Must be the same length as value because we can't know in advance if it s going to be a date or a value
^^^^^^^^^^  the value of variable "max_length" cannot be used as a constant
>>>>    char _buffer_value[max_length];         // buffer for the tag value
^^^^^^^^^^ the value of variable "max_length" cannot be used as a constant

char _buffer_checksum[1];       // buffer for the tag checksum
char _checksum;
char* _buffers[4] = {_buffer_tag, _buffer_date, _buffer_value, _buffer_checksum};
uint8_t _buffer_reference_index;
uint8_t _buffer_index;
...
}

max_length的值因此可以在编译时知道,但是我无法找到一种方法来使用它的值来创建我的数组。

实现我想做的事情的最好方法是什么?因为flash也是一个问题,所以我宁愿避免使用std::vector.

有许多使用预处理器宏和#if语句的选项,这取决于您的需求是什么,您没有明确说明。一个例子是:

#define MaximumLength 8
#if defined ADCO
#if MaximumLength > 12
#undef MaximumLength
#define MaximumLength 12
#endif
#endif
#if defined OPTARIF
#if MaximumLength > 4
#undef MaximumLength
#define MaximumLength 4
#endif
#endif
#if defined ISOUSC
#if MaximumLength > 2
#undef MaximumLength
#define MaximumLength 2
#endif
#endif
#if defined BASE
#if MaximumLength > 9
#undef MaximumLength
#define MaximumLength 9
#endif
#endif
uint8_t max_length = MaximumLength; // If this variable is still desired.
…
char _buffer_date[MaximumLength];

首先,您需要定义变量constconsexpr。因为你的代码已经有错误,你不能用相同的名字重新定义变量,我不确定你打算做什么,但像这样的事情应该工作:

#include <cstdint>
#include <iostream>
#include <algorithm>
// Uncomment line(s) below to check behavior
//#define ADCO
//#define OPTARIF
//#define ISOUSC
//#define BASE
const uint8_t def_max_length = 8;
#ifdef ADCO
const uint8_t max_length = std::max<uint8_t>(def_max_length, 12);
#elif defined(OPTARIF)
const uint8_t max_length = std::max<uint8_t>(def_max_length, 4);
#elif defined(ISOUSC)
const uint8_t max_length = std::max<uint8_t>(def_max_length, 2);
#elif defined(BASE)
const uint8_t max_length = std::max<uint8_t>(def_max_length, 9);
#else
const uint8_t max_length = def_max_length;
#endif
char buffer[max_length];
int main()
{
std::cout << std::size(buffer) << std::endl;
}

如果您需要独立检查所有定义,那么您可以为每个定义定义一个变量,例如:

#ifdef ADCO
const uint8_t max_length_adco = 12;
#else
const uint8_t max_length_adco = 0;
#ednif

然后得到所有变量的最大值:

const uint8_t max_length = std::max({def_max_length, max_length_adco, max_length_optarif, max_length_isousc, max_length_base});

最新更新