Инициализация трехмерного массива двумерными
- Войдите на сайт для отправки комментариев
Вс, 15/12/2019 - 04:52
int pattern_1[8][16] = {{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//drop bomb
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};//siren
int pattern_2[8][16] = {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},//drop bomb
{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};//siren
int song[4][8][16]= {pattern_1, pattern_1, pattern_2, pattern_2};
выдает ошибку array must be initialized with a brace-enclosed initializer
подскажите плиз лучший способ решения задачи, необходимо инициализировать массив содержащий двумерные массивы
Самым простым и логичным решением будет назначить каждый элемент трехмерного массива в цикле. Точнее в трех вложенных циклах.
подскажите плиз лучший способ решения задачи, необходимо инициализировать массив содержащий двумерные массивы
В данном тексте вообще-то Вы не эту задачу пытались решить. Вы пытались сделать в трёхмерном массиве копии двумерных. Т.е. два раза всё в памяти расположить - один раз в двумерных массивах, а потом ещё и в трёхмерном. А учитывая, что в трехмерном ещё и дублируется одно и тоже - так и вообще три раза память занять.
Если надо просто инициализировать, то Вам уже всё подсказал компилятор - надо использовать " brace-enclosed initializer" - какие подсказки Вам ещё нужны? Просто используете как говорят, и всё.
#define pattern_1 {{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} #define pattern_2 {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},\ {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0},\ {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},\ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} int song[4][8][16]= {pattern_1, pattern_1, pattern_2, pattern_2};Другое дело, что непонятно зачем держать в памяти по два одинаковых массива - Вы их что, менять собираетесь по ходу выполнения? А если нет, то нафига дублируете? Не логичнее ли завести указатели и указывать на одно и тоже место?
Ну да, по идее массив song должен содержать в себе указатели на массивы паттернов, правильно?
Самым простым и логичным решением будет назначить каждый элемент трехмерного массива в цикле. Точнее в трех вложенных циклах.
спасибо, этот вариант к сожалению мне не подходит, нужно много наглядно редактируемых пресетов (это драммашинка) и писать для каждого цикла логику их заполнения думаю оверворк
Ну да, по идее массив song должен содержать в себе указатели на массивы паттернов, правильно?
В song четыре паттерна, но на самом деле - две пары одинаковых. Если не предполагается их менять в процессе работы программы, то лучше сделать указателями, чтобы не хранить одинаковые данные в двух разных кусках памяти. А предполагается, или если по какой другой причине они по жизни должны занимать разную память, то можно оставить как я написал
В процессе менять не планируется, это пока так быстрый набросок девайса за вечерок и всю логику еще до конца не продумывал, по идее нужно сделать определенное число редактируемых паттернов например 99, т е это число будет неизменным, и например 10 динамических массивов для сонгов, в которые уже можно забивать любые последовательности паттернов.
int*song[4] = {&pattern_1, &pattern_1, &pattern_2, &pattern_2};будет ли такой вариант правильным? Или нужно указывать полную размерность массиваint*song[4][8][16]?Ни то ни другое.
Если Вам нужен указатель, то для начала определитесь "на что" он указывает. И тогда уж описывайте его тип
Спасибо, по идее получается что мне нужен массив указателей на массивы с паттернами, правильно?
Не знаю, Вам виднее, что Вам нужно.
Ни то ни другое.
Если Вам нужен указатель, то для начала определитесь "на что" он указывает. И тогда уж описывайте его тип
кстати объясните плиз почему ни то и не другое, разве
int*song[4] не массив указателей создаст? {&pattern_1, &pattern_1, &pattern_2, &pattern_2} а эта запись по идее же проинициализируют его ссылками на реальные структуры и не создаст в памяти их копий? Объясните как оно правильно должно быть))кстати объясните плиз почему ни то и не другое, разве
int*song[4] не массив указателей создаст? {&pattern_1, &pattern_1, &pattern_2, &pattern_2} а эта запись по идее же проинициализируют его ссылками на реальные структуры и не создаст в памяти их копий? Объясните как оно правильно должно быть))имя массива в Си - это уже указатель на нулевой элемент. А что такое
&pattern_1 - я даже затрудняюсь сказать, что-то типа адреса указателя....пусть старшие подскажут& - операция взятия адреса. То, на что указывает пойнтер.
int a = 3; int *b = &a;
int*song[4] не массив указателей создаст?ну да, только у массива его имя уже указывает на этот же адрес.
Почитал немного в гугле - разобрался:
если x - это массив, описанный как int x[3], то
x - это адрес нулевого элемента
а &x - это адрес всего массива
Численно эти два значения совпадают, но типы разные, именно поэтому выражение ТС неверное.
Если со второй половиной выражения я более менее понял что в качестве указателя на массив, нужна ссылка на первый элемент массива а не на весь массив, то с первой пока еще не до конца, пока что получается вот так, не знаю насколько оно правильно:
int (*song)[8][16] = {&pattern_1[0], &pattern_1[0], &pattern_2[0], &pattern_2[0]};Если со второй половиной выражения я более менее понял что в качестве указателя на массив, нужна ссылка на первый элемент массива
Нет, с правой частью вы тоже разобрались не до конца. Во-первых, приоритет операции взятия адреса выше, чем получения элемента массива, поэтому запись &x[0] сработает как (&x)[0], а вам надо &(x[0]). Ну а во-вторых - буквально в предыдущем сообщении я написал. что ссылка на первый жлемент массива записывается куда проще - просто x
Что у вас написано в левой части - я вообще не понимаю, обьясните
Загнать все данные в многомерный массив - это принципиальное решение? По-моему задача излишне усложнена.
если x - это массив, описанный как int x[3], то
x - это адрес нулевого элемента
а &x - это адрес всего массива
это как???
это как???
пример попроще. Переменную типа long можно представить как массив байт, верно?
Численное значение ссылок а и b - одинаковое, но тип разный. Точно так же как со сссылкой на массив и на его нулевой элемент.
Боюсь, что это больше заморочки компилятора - не дать программисту путать типы. В реальной памяти, надо думать, "адрес массива" и "адрес нулевого элемента" эквивалентны, коль скоро "индекс есть смещение" ;)
Боюсь, что это больше заморочки компилятора - не дать программисту путать типы. В реальной памяти, полагаю, "адрес массива" и "адрес нулевого элемента" эквивалентны ;)
эквиваленты в том смысле, что ссылка указывает на одну и ту же ячейку памяти. Но не по типу. Точно так же как в примере выше - ссылка на long и на его первый байт - не одно и то же.
Можно я попробую объяснить то, что пытается донести b707? Похоже, нет понимания того, что он хочет сказать. Может, у меня получится.
Вот, смотрите:
Численно f, f1 и f2 равны между собой, но f и f1 - это указатели на первый (нулевой) элемент массива, т.е. указатели на байт!!! А вот f2 - указатель на массив целиком - на 16-тибайтовую область.
Чтобы прочувствовать разницу, запустите вот такой пример и посмотрите на то, что он печатает
#include <Printing.h> byte f[16]; void setup() { Serial.begin(57600); auto f1 = f; auto f2 = &f; printf(" f = %p\r\n", f); printf(" f1 = %p\r\n", f1); printf(" f2 = %p\r\n", f2); // printf("f1+1 = %p\r\n", f1 + 1); printf("f2+1 = %p\r\n", f2 + 1); } void loop() {} // РЕЗУЛЬТАТ // f = 0x158 // f1 = 0x158 // f2 = 0x158 //f1+1 = 0x159 //f2+1 = 0x168Строки №№ 20-22 показывают, что численно все три переменные равны между собой.
В строке №23 мы видим, что при сложении с единицей f1 численно увеличился на 1, это значит, что f1 - указывает на byte. А вот в строке №24 мы видим, что f2 при сложении с 1 увеличился сразу на 16 (0x10), из чего следует, что f2 указывает не на байт, а 16-байтовый кусок памяти, т.е. на массив f целиком.
Гениальна! Просто и наглядно. Спасибо!
Теперь понятно, указатель второго типа позволяет взять адрес конца массива
Теперь понятно, указатель второго типа позволяет взять адрес конца массива
Не только. Если у Вас "массив массивов" как у ТС, он позволяет выбирать нужный "подмассив".
Загнать все данные в многомерный массив - это принципиальное решение? По-моему задача излишне усложнена.
нет, абсолютно не принципиальное, я уже реализовал решение другим способом, но мне хочется разобраться с указателями и ссылками в данном контексте.