Почему нельзя изменить размер массива

0

Похоже на странный вопрос, но когда я программирую в c++ или c, например, мне приходится жестко кодировать размер массива.

Невозможно ли пользователю через терминал ввести размер. Да, я не могу понять, возможно ли это и интересно, почему это запрещено.

РЕДАКТИРОВАТЬ:

До сих пор я понимаю, что массивы являются статическими, и мы можем использовать списки ссылок, поскольку они более динамичны. Почему переменные массивы являются динамическими?

  • 2
    Название говорит об изменении размера массива, который я принимаю как «превратить существующий массив размера N в массив размера M». Но тело, похоже, сосредоточено на создании массива с размером, который определяется во время выполнения, но фиксируется после создания массива. Который из них?
  • 2
    C или C ++? Выберите один, пожалуйста.
Показать ещё 4 комментария
Теги:
arrays

5 ответов

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

Когда вы выделяете блок памяти, вы делаете именно это - блок памяти, размер которого вы запрашиваете, выделяется, и вам предоставляется указатель на него.

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

Для расширения массива вам потребуется больше памяти, но для этого блока недостаточно. Вам нужно выделить новый блок и изменить указатель на этот новый блок, вы не сможете сделать это, изменив размер существующего как пространство после того, как ваш блок уже может быть использован чем-то другим!

Вот почему невозможно изменить размер существующего массива.

  • 0
    Это отвечает на вопрос в названии, но не обязательно на вопрос в теле (я не уверен на 100%).
  • 0
    @delnan Он спросил, почему изменение размера массивов также запрещено в теле вопроса, ответ на этот вопрос, потому что это невозможно из-за того, как память размещена под ними ...
Показать ещё 2 комментария
4

std::vector - динамический массив. Используйте это.

Массивы переменной длины действительно существуют в C и как расширение языка GCC для C++, а в следующем C++ 14 - его внешний вид.


В этом ответе я предположил, что вы имеете в виду массивы, которые могут иметь границы времени выполнения, даже если эти границы не могут быть впоследствии изменены.Это соответствует содержимому вашего вопроса, но не его название.К счастью, std::vector обеспечивает оба.

Я также предположил C++, потому что кого мы шутим?

3

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

В C вы сами контролируете эти операции изменения размера, используя кучу и malloc/realloc, потому что это тип языка C. C++ имеет массивы, которые делают это для вас, как std :: vector, или даже в C вы можете использовать библиотечные функции для управления динамическими массивами. Просто простой массив C спроектирован так, чтобы быть простым и быстрым.

3

С

В C99 и более новых стандартах вы можете использовать VLA:

int len = ask_length_from_user();
int array[len];
for (int i = 0; i < len ; ++i) array[i] = i;

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

Возможно, лучше использовать кучу:

int len = ask_length_from_user();
int *array = malloc (sizeof(int) * len);
if (!array) exit(1); // malloc failed
for (int i = 0; i < len ; ++i) array[i] = i;

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

int tmplen = ask_length_from_user();
int *tmparr = realloc(array, sizeof(int) * tmplen);
if (tmparr) {
    array = tmparr;
    // note: following loop doesn't do anything if len >= newlen
    while(len < tmplen) array[len++] = len;
}
// else realloc failed, keep original array and len

Наконец, с памятью malloc, помните!

free(array);

C++

Вы должны использовать, например, std :: vector:

int len = ask_length_from_user();
std::vector<int> array;
for (int i = 0; i < len ; ++i) array.push_back(i);

// alternatively, you can resize the array and use indexes like in C snippets:
array.resize(len);
for (int i = 0; i < len ; ++i) array[i] = i;

И код для изменения размера, просто с push_back:

int tmplen = ask_length_from_user();
if (tmplen < len) { 
    len = tmplen;
    array.resize(tmplen);
} else {
    while (len < tmplen) array.push_back(len++);
}

Как вы можете видеть, коды C и C++ совершенно разные. Это разные языки, и редко бывает разумно задавать одно и то же. C-код (кроме VLA в текущем стандарте C++) будет работать в C++, но делать это не очень хорошо, это нехорошо C++, и по крайней мере вам следует избегать malloc и использовать new (хотя он не поддержка изменения размеров красиво).

  • 0
    Во втором примере вам не хватает, используя размер std::vector<int> array(len); или array.resize(len); [перед циклом]
  • 0
    @MatsPetersson Да, ошибка копирования-вставки, я действительно хотел использовать push_back
0

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

Но для изменения размера массива вам не нужно C99 или vector. Вы всегда можете выделить динамическую память в куче и использовать указатель как массив, потому что они не "разные" при использовании этого способа. Динамическая память изменяется при распределении новой области памяти и при необходимости копирует данные в новое место.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню