【问题标题】:Arduino accessing array produces unexpected resusltsArduino 访问数组会产生意想不到的结果
【发布时间】:2017-03-07 17:05:02
【问题描述】:

我正在尝试在我的 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
------

【问题讨论】:

  • 那不是 C! Arduino 不是 C!
  • 为什么投反对票?这是一个有趣的问题(现在标记为 C++)。

标签: c++ arrays arduino avr progmem


【解决方案1】:

来自avr-libc - source code

strlen_P()avr/pgmspace.h 中作为内联函数实现 头文件,会检查字符串的长度是否为 常量并且在编译时已知。如果在编译时不知道 时间,宏将调用__strlen_P(),然后 正常计算字符串的长度。

这可以解释它(尽管调用 __strlen_P() 应该可以解决这个问题)。

也许改用以下内容:

strlen_P((char*)pgm_read_word(&(string_table[i])));

或者可以尝试使用strlen_PF()

【讨论】:

  • strlen_P((char*)pgm_read_word(&amp;(string_table[i]))); 是解决方案。感谢您的简明解释,也感谢您没有否决我的问题。
猜你喜欢
  • 1970-01-01
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 2019-04-05
  • 1970-01-01
  • 2021-12-28
  • 2021-10-04
相关资源
最近更新 更多