如何将字符数组定义为常量

How do you define a char array as a constant?

本文关键字:定义 常量 数组 字符      更新时间:2023-10-16

C/c++新手。我已经在头文件中定义了这个…

typedef unsigned char BitChar[9]; // 8 data bytes (chars) and one width byte (char)
extern BitChar BitFont[];

我把它放在一个cpp文件中…

BitChar BitFont[] = {
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,2, // 32 - Space
    B10000000,B10000000,B10000000,B10000000,B10000000,B00000000,B10000000,B00000000,1, // 33 - !
    ...
    B00000000,B00000000,B11100000,B11100000,B11100000,B00000000,B00000000,B00000000,3, // 127 - Unknown
};

它可以编译并且看起来运行得很好。但是,由于它永远不会改变,我认为它应该被标记为常数。我如何标记它呢?我所期望的,添加'const',抛出编译错误,所以我被难住了。这里是错误…

error: invalid initialization of reference of type 'unsigned char (&)[9]' from expression of type 'const unsigned char [9]' 

添加const。这个

extern const BitChar BitFont[];
...
const BitChar BitFont[] = {
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,2, // 32 - Space
    B10000000,B10000000,B10000000,B10000000,B10000000,B00000000,B10000000,B00000000,1, // 33 - !
    ...
    B00000000,B00000000,B11100000,B11100000,B11100000,B00000000,B00000000,B00000000,3, // 127 - Unknown
};

在c语言中应该可以很好地工作(假设你的编译器知道这些B00000000标识符的含义)

在c++中也可以很好地工作。c++版本中唯一可能出现错误的是基于const的c++特定属性。如果定义没有看到声明,那么您也必须在定义中指定显式的extern

extern const BitChar BitFont[] = {
    B00000000
    ...

因为在c++中const对象默认具有内部链接。但是,如果声明中已经包含extern,并且定义可以看到该声明,则定义中的extern是可选的。

你引用的错误信息表明,在你的代码的某个地方,你正试图初始化类型BitChar &(又名unsigned char (&)[9])的引用与const限定的BitChar数组。这是行不通的,因为它违反了常量正确性的基本规则。引用也必须成为const限定的,即它必须更改为const BitChar &(也称为const unsigned char (&)[9])。

请注意CONST仍然会消耗RAM空间。对于大型常量数组,您可能需要考虑将它们放入程序空间(又名Flash或非易失性空间)。下面是一个例子:

const uint8_t BitFont[] PROGMEM = {
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,2, // 32 - Space
    B10000000,B10000000,B10000000,B10000000,B10000000,B00000000,B10000000,B00000000,1, // 33 - !
    B00000000,B00000000,B11100000,B11100000,B11100000,B00000000,B00000000,B00000000,3, // 127 - Unknown
};
#define BITFONT_X_SIZE (sizeof(BitFont)/sizeof(BitFont[0]))
void setup() {
  Serial.println("");
  Serial.print(F("BitFont[] = "));
  for(int y = 0 ; y < BITFONT_X_SIZE ; y++) {
    Serial.print(pgm_read_byte_near( &(BitFont[1]) ) );
    Serial.print(F(","));
  }
  Serial.println("");
}

注意有三件事正在发生。首先,avr-gcc使用program宏将其链接到程序空间。其次,pgm_read_byte_near函数用于从程序空间读取指针。因为它需要使用一个特殊的操作码来读取程序空间。

第三,与您的示例没有直接关系,但类似的是在Serial.print()中使用的F()函数,它同样将常量字符串放入程序空间。的字符串。打印消耗静态内存。


或者你可以创建一个矩阵

#define BRICK_COLUMNS 9
const uint8_t BitFont[][BRICK_COLUMNS] PROGMEM = {
    {B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,2}, // 32 - Space
    {B10000000,B10000000,B10000000,B10000000,B10000000,B00000000,B10000000,B00000000,1}, // 33 - !
    {B00000000,B00000000,B11100000,B11100000,B11100000,B00000000,B00000000,B00000000,3} // 127 - Unknown
};
#define BITFONT_X_SIZE (sizeof(BitFont)/sizeof(BitFont[0]))
void setup() {
  Serial.println("");
  for(int x = 0 ; x < BITFONT_X_SIZE ; x++) {
    Serial.print(F("BitFont["));
    Serial.print(x);
    Serial.print(F("][y] = "));
    for(int y = 0 ; y < BRICK_COLUMNS ; y++) {
      Serial.print(pgm_read_byte_near ( &(BitFont[1]) ));
      Serial.print(F(","));
    }
    Serial.println("");
  }
  Serial.println("");
}