Почему это не удается после 3 итераций?

Я просто не могу этого понять, почему это не удается после трех итераций? Кроме этого, какой лучший способ сделать это? Спасибо!

#define rotary_encoder_topic  "/rotary/encoder"
#define remote_button_topic  "/remote/button"
#define remote_2x_toggle_topic  "/remote/2xtoggle"
#define rotary_button_topic  "/rotary/button";
char* devices[] = { "ledrpi", "lamprpi", "mediaroom" };
int currentDevice = 0;

void setup() {
  Serial.begin(115200);
}

void incrementCurrentDevice() {
  currentDevice++;
  if (currentDevice >= sizeof(devices)) {
    currentDevice = 0;
  }
 Serial.println(concatenateChars("Switched device to: ", devices[currentDevice]));
}

char* concatenateChars(const char* one, const char* two) {
  char result[150] = "";
  strcat(result, one);
  strcat(result, two);
  return result;
}

void loop() {
  Serial.println(concatenateChars(devices[currentDevice], remote_2x_toggle_topic));
  incrementCurrentDevice();
  delay(1000);
}

, 👍0

Обсуждение

что значит «провал»?, @jsotola


1 ответ


1

Как отметил Джароманда X в комментариях, sizeof(array[0]) (размер первого элемента) вернет не размер литеральных строк, а размер указатель char.


Это не работает (что бы это ни значило для вас), потому что sizeof(devices) возвращает не количество записей в массиве, а размер массива в байтах, например что-то вроде (неправильно следующее: 24 (1 байт на символ плюс 1 байт с завершающим нулевым символом для каждой строки)) 6 (Размер указателя char составляет 2 байта на большинстве микроконтроллеров; I' Я не уверен, что это то же самое для Node MCU). Таким образом, после трех итераций (которые могут использовать строковые литералы в массиве) currentDevice не возвращается к нулю, а продолжает считать. При доступе к массиву с индексом, превышающим индекс, вы получаете доступ к памяти, которая больше не принадлежит массиву (например, случайным данным).

Не существует встроенной функции, которая бы определяла длину массива. Но его можно вычислить с помощью sizeof(array)/sizeof(array[0]), который представляет собой размер массива в байтах, разделенный на размер одного элемента в байтах. В вашем случае у вас будет размер массива 6 и размер элемента 2, в результате чего вычисленное количество элементов будет равно 3, что правильно.

Еще одно простое решение, которое легче понять новичкам, но не такое гибкое — установить константу или определение, содержащее размер вашего массива. Затем вы сможете использовать его в своем коде всякий раз, когда вам понадобится размер, в том числе при определении массива.

,

на самом деле sizeof(devices) не вернет 3 x sizeof(char *), поэтому длина каждой строки не имеет значения. поэтому sizeof(array)/sizeof(array[0]) в этом случае гарантированно даст 3, @Jaromanda X

конечно, я имел в виду sizeof(devices)/sizeof(devices[0])`, @Jaromanda X

@JaromandaX Ммм, я не подумал об этом. Но я думаю, вы правы. Размер указателя, насколько я помню, 2 байта. Таким образом, это будет считаться до 6. Это то же самое для Node MCU? И да, разделение должно работать в любом случае., @chrisl

знание размера указателя на самом деле не имеет значения: D, @Jaromanda X

В данном случае это не имеет значения, но мне было интересно, @chrisl