объявление самого большого массива с помощью size_t - PullRequest
3 голосов
/ 12 октября 2010

Я хотел объявить очень большой массив. я обнаружил, что максимальный размер массива - size_t, который определяется как UINT_MAX

поэтому я написал код, подобный этому

int arr[UINT_MAX];

когда я компилирую это, он говорит переполнение в измерении массива

но когда я пишу так

size_t s = UINT_MAX;
int arr[s]; 

правильно компилируется. какая разница

Ответы [ 6 ]

14 голосов
/ 13 октября 2010

Первая ошибка: size_t не обязательно unsigned int, поэтому его максимальное значение может отличаться от значения unsigned int (UINT_MAX);более того, в C ++ для получения информации об ограничениях типа вы должны использовать std::numeric_limits.

#include <limits>

size_t s=std::numeric_limits<size_t>::max();

Вторая ошибка: массив никогда не будет таким большим;поскольку size_t требуется, чтобы иметь возможность выразить самый большой размер любого объекта, он, вероятно, должен быть достаточно большим, чтобы выразить объект, большой как все адресное пространство, доступное для приложения, но попытка выделить такой большой объект потребовала бы выделения целое адресное пространство для него, что недопустимо;более того, вы запрашиваете массив размером int s, что означает, что он будет иметь размер UINT_MAX*sizeof(int) байт, что, вероятно, будет примерно в 4 раза больше всего адресного пространства - явно бессмысленным - и, кстати, sizeof(arr)не смог бы выразить размер такого объекта, и вообще указатели не могли бы даже достичь вершины этого массива.Компилятор обнаруживает эти ошибки и мешает вам сделать это.

Более того, я делаю вывод, что вы пытаетесь выделить эту вещь в стеке, которая обычно намного меньше, чем вся память, которую может использовать приложение.и вообще нецелесообразно размещать там большие массивы (для этого следует использовать кучу).

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

Второй фрагмент кода в C ++ даже не должен работать, поскольку, если эта вещь размещена в стеке, вы собираетесь работать нестандартно, поскольку онабудет VLA (доступно в C99, но категорически отвергается из текущего и следующего стандарта C ++).Однако в этом случае код для выделения этого массива используется во время выполнения (VLA в общем случае не являются фиксированными в измерениях), поэтому проверка компилятора не очевидна (хотя я предполагаю, что эта вещь может быть легко обнаруженаоптимизатор, который, если семантика VLA не отличается от обычных массивов, может оптимизировать VLA и попытаться создать обычный массив =>, который не будет работать по тем же причинам, о которых я говорил).

Короче говоря: этонет смысла выделять всю эту память (которую вы даже не могли бы адресовать), особенно в стеке.Используйте кучу и выделите именно то, что вам нужно.Если у вас есть особые требования, вам следует изучить специальные функции виртуальной памяти, предоставляемые вашей ОС.

2 голосов
/ 12 октября 2010

Вы задерживаете ошибку.

Вы запрашиваете около 16 ГБ * непрерывной памяти в обоих случаях, что невозможно на 32-разрядной машине.

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

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

* на типовых архитектурах

0 голосов
/ 01 мая 2013

для каждого беззнакового целочисленного типа максимум должен быть представлен -1.Например, в 64-разрядной системе следующий код

unsigned char uchar_max = -1;
printf("%u\n", uchar_max);
unsigned int uint_max = -1;
printf("%u\n", uint_max);
unsigned long ulong_max = -1;
printf("%lu\n", ulong_max);
size_t sizet_max = -1;
printf("%lu\n", sizet_max);

возвращает:

255
4294967295
18446744073709551615
18446744073709551615
0 голосов
/ 12 октября 2010

Какой компилятор вы используете?На VC ++ я получаю ошибку в обоих случаях (после исправления s, чтобы быть const).Даже если он скомпилируется, это приведет к неопределенному поведению, поскольку UINT_MAX * sizeof(int) определенно не поместится в адресное пространство вашего процесса, и, кроме того, само целочисленное значение будет переполнено и приведет к неправильному значению размера.

0 голосов
/ 12 октября 2010
size_t s = UINT_MAX;
int arr[s];

означает, что arr является массивом переменной длины (VLA).Я думаю, что это не разрешено в соответствии со стандартом C ++.Я ожидал бы предупреждение, если скомпилировано с

g++ -ansi -pedantic -std=c++98

Кроме того, подумайте об этом, arr требуется UINT_MAX * sizeof( int ) количество байтов.Это довольно большой!

0 голосов
/ 12 октября 2010
size_t s = UINT_MAX;
int arr[s];  

не скомпилируется, если вы не объявите s как const.Также обратите внимание, что UINT_MAX - потенциально самый большой размер массива.Практически это не позволит вам объявить массив размером более нескольких миллионов.Это потому что статический и автоматический и любая память ограничена

...