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
中,对象默认具有internal链接。但是,如果声明中已经包含extern
并且定义可以看到该声明,则定义中的extern
是可选的。
您引用的错误消息表明,您试图在代码中的某个地方尝试使用const限定的BitChar &
数组初始化类型为unsigned char (&)[9]
(又名BitChar
)的引用。这将不起作用,因为它违反了const-correctity的基本规则。该引用也必须成为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使用PROGMEM宏将其链接到程序空间。其次,使用pgm_read_byte_near函数从程序空间读取指针。因为它需要使用特殊的操作码来读取程序空间。
第三,与您的示例没有直接关系,但是与Serial.print()中使用的F()函数类似,该函数同样将常量字符串放入程序空间。否则,Serial.print中的字符串会消耗静态内存。
或者您可以创建矩阵
#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("");
}