Как объявить массив переменного размера (глобально)

Я хочу сделать три массива одинаковой длины. Согласно документации, массивы должны быть определены как int myArray[10]; где 10 может быть заменено на известную длину (другое целое число) или заполнено массивом {2, 3, 5, 6, 7}.

Однако, когда я попытался объявить значение int arrSize = 10; а затем массив, основанный на этом размере int myArray[arrSize];, я получаю следующее: error: array bound is not an integer constant.

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

, 👍19

Обсуждение

У меня была похожая проблема, и я сделал это. Я тоже учусь, поэтому не могу сказать, является ли это действительным решением или нет, но оно сработало. См. Ниже часть кода с использованием векторов, мне потребовалось совсем немного, чтобы начать понимать их, и я до сих пор ни в коем случае не эксперт: #include <string>#include <vector>#include <iostream>#include <algorithm>#include <string.h>using namespace std; int main() { string name; string address; string town; string country; string answer; vector<vector<string>> PersonData; for(;;) { vector<string> myTempData; cout<<"введите имя или n для выхода"<, @Misterxp


5 ответов


Лучший ответ:

29

На самом деле ваш вопрос состоит из 2 частей.

1/ Как я могу объявить постоянный размер массива вне массива?

Вы можете использовать макрос

#define ARRAY_SIZE 10
...
int myArray[ARRAY_SIZE];

или используйте константу

const int ARRAY_SIZE = 10;
...
int myArray[ARRAY_SIZE];

если вы инициализировали массив и вам нужно знать его размер, то вы можете сделать следующее:

int myArray[] = {1, 2, 3, 4, 5};
const int ARRAY_SIZE = sizeof(myArray) / sizeof(int);

второй sizeof зависит от типа каждого элемента вашего массива, здесь int.

2/ Как я могу иметь массив, размер которого является динамическим (т. Е. Не известен до времени выполнения)?

Для этого вам понадобится динамическое распределение, которое работает на Arduino, но обычно не рекомендуется, так как это может привести к фрагментации "кучи".

Вы можете сделать (C путь):

// Объявление
int* myArray = 0;
int myArraySize = 0;

// Распределение (предположим, размер содержит некоторое значение, обнаруженное во время выполнения,
// e.g. obtained from some external source)
if (myArray != 0) {
    myArray = (int*) realloc(myArray, size * sizeof(int));
} else {
    myArray = (int*) malloc(size * sizeof(int));
}

Или (способ C++):

// Объявление
int* myArray = 0;
int myArraySize = 0;

// Allocation (предположим, size содержит некоторое значение, обнаруженное во время выполнения,
// e.g. obtained from some external source or through other program logic)
if (myArray != 0) {
    delete [] myArray;
}
myArray = new int [size];

Подробнее о проблемах с фрагментацией кучи вы можете узнать из этого вопроса.

,

1) ARRAY_SIZE = sizeof myArray / sizeof myArray[0];, таким образом, вы можете изменить тип myArray без внесения ошибок. По той же причине myArray = realloc(myArray, size * sizeof *myArray);. Кстати, приведение возвращаемого значения malloc() или realloc() также бесполезно. 2) Проверка myArray != 0 в версии C бесполезна, так как realloc(NULL, sz) эквивалентно malloc(sz)., @Edgar Bonet

const int ARRAY_SIZE = 10; int myArray[ARRAY_SIZE]; Вы действительно думаете, что это возможно?. Это дало бы изменяемую ошибку массива в C., @Arun Joe Cheriyan

@ArunCheriyan в C я не знаю, но в C++ он компилируется и работает отлично. Поскольку Arduino основан на C++, то здесь нет никаких проблем., @jfpoilpret

Может быть одна из причин безопасного использования динамической памяти на Arduino-это когда вы БОЛЬШЕ НЕ удаляете эту память и не используете ее повторно, так что только для целей "инициализации". Вам просто нужно убедиться, что общий объем динамической памяти достаточен, чтобы оставить место для другой динамической памяти (включая аргументы функций/методов, которые попадают в стек)., @Michel Keijzers


0

Размер массива должен быть известен во время компиляции. В противном случае вы должны выделять память динамически, используя:

char *chararray = malloc(sizeof(char)*x);

где x(целое число) может быть задано в коде приложения (вы можете загрузить его из eeprom, если хотите, чтобы он был постоянным, но настраиваемым параметром).


Однако если вы просто хотите объявить несколько массивов одинакового размера, вам просто нужно объявить число константой следующим образом:

const int arrsize = 10;
char array1[arrsize];
int array2[arrsize];

Я думаю, что не жесткое кодирование вещей имеет смысл только в том случае, если вы разумно ожидаете, что пользователь захочет изменить настройку в какой-то момент. Я не знаю, так ли это.

,

Кодирование размеров символически, а не буквально, может дать два преимущества: 1) Хорошо выбранный символ документирует или, по крайней мере,подсказывает причину выбора; и 2) когда другие части программы или модуля должны быть адаптированы к этому выбору, выражение, использующее тот же символ, может сделать это автоматическим. что значительно облегчает техническое обслуживание., @JRobert

[Немного не по теме, но] "пользователь" неоднозначен, поскольку он может означать одного из нескольких людей. Под ним обычно подразумевается конечный пользователь, потребитель конечного продукта, если не указано иное. Это может быть следующий программист, непосредственно следующий потребитель вашего кода, который на самом деле может быть *вами* (типично, по моему собственному опыту) через год или больше после того, как я забуду его мельчайшие внутренние детали). Или системный дизайнер, который включает ваш код в качестве готового модуля в свой продукт. Я подозреваю, что вы имели в виду второго "пользователя"., @JRobert


1

Если вы знаете максимальную длину массива, просто инициализируйте массив до этой длины и используйте целое число, чтобы сообщить программе, какую часть этого массива использовать. Если это разница между 7,10 байтами, то вы не тратите столько памяти впустую.

,

2

Я знаю, что немного опоздал, но теоретически обычные массивы не могут быть созданы с помощью переменной, определяющей количество элементов, которые будет иметь массив, как в:

int arrSize;
int myArray[arrSize];

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

//Сначала вы создаете указатель на пространство памяти, которое будет разделено для набора, который вы создаете
int* myArray;
int arrSize; //Затем вы определяете переменную, которая будет определять количество элементов, которые будет иметь массив, вы можете дать ему значение всякий раз, когда захотите. этот int определяется до того, как будут установлены значения в myArray 
myArray=(int*)calloc(arrSize,sizeof(int)) //Здесь вы устанавливаете, что экземпляр myArray (пространство памяти которого уже было разделено при создании указателя) будет разделен на arrSize количество элементов типа int с максимальным значением памяти (в байтах). равно максимуму, доступному для переменных типа int

После этого все, что осталось сделать, это присвоить значение каждому элементу, созданному в экземпляре myArray (который к настоящему времени уже является массивом), как это было бы для обычного массива, созданного как myArray[arrSize].

,

0

Coderwall довольно подробно объясняет теорию о том, как лучше всего получить размер массива в C++ https://coderwall.com/p/nb9ngq/better-getting-array-size-in-c

,

Привет, Джон, добро пожаловать на Arduino Stack Exchange! У нас есть общее правило, что ответы не должны быть просто ссылками, так как ссылки (к сожалению) опускаются, и тогда ответ бесполезен. Пожалуйста, обобщите или перепечатайте информацию в ответе прямо здесь (я замечаю, что она довольно короткая), чтобы ее полезность не исчезла. Я предлагаю вам дать кредит, сославшись на сайт, или на имя автора, или на то и другое вместе., @Nick Gammon

Лучше включить свой собственный короткий ответ и ссылаться только на источник. В противном случае ответ не поможет, когда сайт, на который вы ссылаетесь, будет удален., @Sim Son