Arduino 访问数组产生意想不到的结果
Arduino accessing array produces unexpected resuslts
我正在尝试读取 Arduino UNO 闪存中一些字符串的长度。数组 string_table
给我带来了问题,如果我用编译器优化为常量的东西得到它的索引,那么我就会得到预期的值。如果我在 运行 时使用变量访问它,那么每次我都会得到不同的答案。
我认为这不是 Arduino 特有的,因为我似乎没有调用任何 Arduino 特定的功能。
代码:
#include <avr/pgmspace.h>
// Entries stored in flash memory
const char entry_0[] PROGMEM = "12345";
const char entry_1[] PROGMEM = "abc";
const char entry_2[] PROGMEM = "octagons";
const char entry_3[] PROGMEM = "fiver";
// Pointers to flash memory
const char* const string_table[] PROGMEM = {entry_0, entry_1, entry_2, entry_3};
void setup() {
Serial.begin(115200);
randomSeed(analogRead(0));
int r = random(4);
Serial.print("random key (r) : ");
Serial.println(r);
Serial.print("Wrong size for key = ");
Serial.print(r);
Serial.print(" : ");
Serial.println(strlen_P(string_table[r]));
int i = 1;
Serial.print("Correct size for key = ");
Serial.print(i);
Serial.print(" : ");
Serial.println(strlen_P(string_table[i]));
Serial.println("=====");
Serial.println("Expected Sizes: ");
Serial.print("0 is: ");
Serial.println(strlen_P(string_table[0]));
Serial.print("1 is: ");
Serial.println(strlen_P(string_table[1]));
Serial.print("2 is: ");
Serial.println(strlen_P(string_table[2]));
Serial.print("3 is: ");
Serial.println(strlen_P(string_table[3]));
Serial.println("++++++");
Serial.println("Wrong Sizes: ");
for (i = 0; i < 4; i++) {
Serial.print(i);
Serial.print(" is: ");
Serial.println(strlen_P(string_table[i]));
}
Serial.println("------");
delay(500);
}
void loop() {
// put your main code here, to run repeatedly:
}
结果:
random key (r) : 1
Wrong size for key = 1 : 16203
Correct size for key = 1 : 3
=====
Expected Sizes:
0 is: 5
1 is: 3
2 is: 8
3 is: 5
++++++
Wrong Sizes:
0 is: 0
1 is: 11083
2 is: 3
3 is: 3
------
来自avr-libc - source code:
strlen_P()
is implemented as an inline function in the avr/pgmspace.h
header file, which will check if the length of the string is a
constant and known at compile time. If it is not known at compile
time, the macro will issue a call to __strlen_P()
which will then
calculate the length of the string as normal.
这可以解释它(尽管对 __strlen_P()
的调用应该已经解决了)。
也许可以改用以下内容:
strlen_P((char*)pgm_read_word(&(string_table[i])));
或者尝试使用 strlen_PF()
。
我正在尝试读取 Arduino UNO 闪存中一些字符串的长度。数组 string_table
给我带来了问题,如果我用编译器优化为常量的东西得到它的索引,那么我就会得到预期的值。如果我在 运行 时使用变量访问它,那么每次我都会得到不同的答案。
我认为这不是 Arduino 特有的,因为我似乎没有调用任何 Arduino 特定的功能。
代码:
#include <avr/pgmspace.h>
// Entries stored in flash memory
const char entry_0[] PROGMEM = "12345";
const char entry_1[] PROGMEM = "abc";
const char entry_2[] PROGMEM = "octagons";
const char entry_3[] PROGMEM = "fiver";
// Pointers to flash memory
const char* const string_table[] PROGMEM = {entry_0, entry_1, entry_2, entry_3};
void setup() {
Serial.begin(115200);
randomSeed(analogRead(0));
int r = random(4);
Serial.print("random key (r) : ");
Serial.println(r);
Serial.print("Wrong size for key = ");
Serial.print(r);
Serial.print(" : ");
Serial.println(strlen_P(string_table[r]));
int i = 1;
Serial.print("Correct size for key = ");
Serial.print(i);
Serial.print(" : ");
Serial.println(strlen_P(string_table[i]));
Serial.println("=====");
Serial.println("Expected Sizes: ");
Serial.print("0 is: ");
Serial.println(strlen_P(string_table[0]));
Serial.print("1 is: ");
Serial.println(strlen_P(string_table[1]));
Serial.print("2 is: ");
Serial.println(strlen_P(string_table[2]));
Serial.print("3 is: ");
Serial.println(strlen_P(string_table[3]));
Serial.println("++++++");
Serial.println("Wrong Sizes: ");
for (i = 0; i < 4; i++) {
Serial.print(i);
Serial.print(" is: ");
Serial.println(strlen_P(string_table[i]));
}
Serial.println("------");
delay(500);
}
void loop() {
// put your main code here, to run repeatedly:
}
结果:
random key (r) : 1
Wrong size for key = 1 : 16203
Correct size for key = 1 : 3
=====
Expected Sizes:
0 is: 5
1 is: 3
2 is: 8
3 is: 5
++++++
Wrong Sizes:
0 is: 0
1 is: 11083
2 is: 3
3 is: 3
------
来自avr-libc - source code:
strlen_P()
is implemented as an inline function in theavr/pgmspace.h
header file, which will check if the length of the string is a constant and known at compile time. If it is not known at compile time, the macro will issue a call to__strlen_P()
which will then calculate the length of the string as normal.
这可以解释它(尽管对 __strlen_P()
的调用应该已经解决了)。
也许可以改用以下内容:
strlen_P((char*)pgm_read_word(&(string_table[i])));
或者尝试使用 strlen_PF()
。