Можно ли в многомерных массивах использовать переменные массивы или их имена вместо фактических данных?

Ссылка на этот поток Как объявить и использовать "Переменные массивы" внутри массивов

Пример

byte array[2][4] = { {1,2,3,4}, {5,6,7,8} };
Serial.println(array[0][2]); равно '3'.

Вместо использования {1, 2, 3, 4} и {5, 6, 7, 8} я хочу иметь возможность объявлять отдельные массивы для каждого из них и просто ставить имя.

Еще одна большая проблема-это размещение массивов разных размеров для каждой записи, и было бы неправильно делать это. Неужели это действительно невозможно? Нужно ли вместо этого использовать какую-то другую концепцию, если я хочу иметь массив, содержащий записи массивов разных размеров? Я слышал об указателях, но не знаком с этим.

Пример,

byte arrayX[3] = {1, 2, 3}
byte arrayY[4] = {5, 6, 7, 8}

byte array[2][4] = { arrayX , arrayY };

Обратите внимание, что код не был взят из ссылки, которую я упомянул, я просто использовал те же имена массивов. Также я изменил arrayX со ссылки на 3 записи, потому что я хочу подчеркнуть часть моего вопроса, возможно ли, если массивы имеют разные размеры, и вы просто используете самый большой размер?

Теперь я думаю, что это неправильно, и я не тестировал его в настоящее время, но я хочу спросить, есть ли решение, которое использует то, что я упомянул? Сайт, на который я ссылался, дал решение, которое кажется мне очень избыточным с точки зрения декларации, и я бы этого не хотел. Это решение, упомянутое там.

byte arrayZ[2][4] = {
  {arrayX[0],arrayX[1],arrayX[2],arrayX[3]},
  {arrayY[0],arrayY[1],arrayY[2],arrayY[3]}
};

Проблема, с которой я столкнулся при поиске в Интернете, та же, что и со ссылкой. - Я искал в Интернете кучу примеров, но разница лишь в том, что они не используют массивы, которые были объявлены с именем внутри массива.

, 👍2

Обсуждение

Вот [все, что вы когда-либо хотели знать о взаимосвязи между массивами и указателями](http://c-faq.com/aryptr/index.html) (и еще больше). Обратите внимание, что речь идет о C, а в C++ есть некоторые дополнительные функции, на которые ссылается назойливый пользователь в своем ответе., @Edgar Bonet


1 ответ


2

Двумерные массивы бывают двух видов. На самом деле многомерные массивы возможны в любой их комбинации.

  • Все элементы в прямоугольной сетке, по крайней мере с абстрактной точки зрения языка программирования;
  • Одномерный массив одномерных массивов.

Если вы заявляете:

byte array[n][m];

затем вы зарезервировали место для "n раз m" байтов. С точки зрения программиста это прямоугольная сетка, на самом деле все байты расположены последовательно в одномерном массиве. Это происходит потому, что память наших компьютеров обычно организована как большой одномерный массив байтов. Компилятор генерирует правильный расчет смещения в этом массиве, умножая один индекс на размер ширины (или длины, в зависимости от вашей ментальной модели) и добавляя другой индекс.

Вы можете инициализировать такой массив вложенным набором фигурных скобок следующим образом:

byte array[n][m] = {
    { /* ... */ },
    /* ... */
};

Но вы не можете инициализировать его, как вы показываете.

В противном случае, если вы объявите

byte* array[n];

затем вы повторно сохранили пространство для указателей "n" на байты, то есть одномерный массив указателей. Каждый из этих указателей может указывать на другой или тот же одномерный массив байтов или на отсутствие массива вообще, если это nullptr.

Теперь вы можете настроить массив так, как вам нравится:

byte arrayX[m1] = { /* ... */ };
byte arrayY[m2] = { /* ... */ };

byte* array[n] = { arrayX, arrayY, /* ... */ };

Массивы arrayX и arrayY (и любые другие) не должны иметь одинаковую длину. Каждый может иметь свою длину. Но будьте осторожны, вам нужно как-то отследить длину, чтобы избежать доступа за пределы. И, конечно, перед разыменованием указателя необходимо проверить или убедиться, что он не является нулевым.

В обоих случаях вы можете получить доступ к одному элементу с помощью:

byte element = array[i][j];
array[k][l] = 23;

Это связано с тем, что синтаксис со скобками эквивалентен оператору разыменования:

x[y] == *(x + y)

Примечание 1: Поскольку ардуино запрограммированы на C++, есть еще один вариант. Вместо указателей можно использовать ссылки. Поскольку действительно трудно создать нулевую ссылку, некоторые рассматривают ее как меру безопасности против нулевых указателей.

Примечание 2: Опять же, поскольку ардуино запрограммированы на C++, вы можете реализовать собственный класс, предоставляющий оператор[]. С помощью этой опции вы можете делать любые магические вещи, но это может нарушить ожидания пользователя. Будьте осторожны, если пойдете этим путем.

,