如何使我的char数组保持不变?

时间:2014-08-15 03:19:22

标签: c++ c arduino const

C / C ++ noob。我在头文件中定义了这个...

typedef unsigned char BitChar[9]; // 8 data bits and one width bit

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]' 

2 个答案:

答案 0 :(得分: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 ++版本中唯一的错误可能是基于C ++特定的const属性。如果定义没有看到声明,那么你必须在定义中指定显式的extern

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

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

您引用的错误消息表明您在代码中的某个位置尝试使用const限定的BitChar &数组初始化类型为unsigned char (&)[9](aka BitChar)的引用。这不起作用,因为它违反了const-correctness的基本规则。引用也必须符合const限定条件,即它必须更改为const BitChar &(又名const unsigned char (&)[9])。

答案 1 :(得分:1)

请注意,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使用PROGMEM宏将其链接到程序空间。其次,pgm_read_byte_near函数用于从程序空间读取指针。因为它需要使用特殊的操作码来读取程序空间。

第三,与你的例子没有直接关系,但类似的是Serial.print()中使用的F()函数,它同样将常量字符串放入程序空间。否则,Serial.print中的字符串将使用静态ram。


或者你可以创建一个矩阵

#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("");
}