2010-10-12 2 views
3

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

так я написал код, как этот

int arr[UINT_MAX]; 

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

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

size_t s = UINT_MAX; 
int arr[s]; 

он скомпилируется должным образом. какая разница

+1

Какой компилятор это? FYI с 'const' на' size_t', оба сбой в Visual C++ v10 с «общим размером массива не должны превышать 0x7fffffff байтов» –

+1

«Я обнаружил, что максимальный размер массива - size_t» - это неверно, 'size_t 'не является константой, это тип (точный тип typedef для неподписанного типа данных). Фактический базовый тип данных зависит от платформы. Вы можете использовать 'std :: numeric_limits :: max()' для получения максимального значения, которое может храниться в переменной типа 'size_t'. – Praetorian

+0

И оба эти фрагмента кода производят эту ошибку в Visual Studio 2005: «ошибка C2148: общий размер массива не должен превышать 0x7fffffff байтов» – Praetorian

ответ

14

Первая ошибка: 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 и попытаться сделать регулярный массив =>, который потерпит неудачу по тем же причинам, которые я изложил).

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

+0

+1 для обозначения обычно меньшего размера стека. –

0
size_t s = UINT_MAX; 
int arr[s]; 

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

0
size_t s = UINT_MAX; 
int arr[s]; 

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

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

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

+0

g ++ компилятор позволяет vla. c99 также позволяет это. – ameen

+0

Вы правы. Я подозреваю, что компилятор разрешает прокручивать функции C99, но это не переносимый код. –

+0

Вы видите, это была моя точка в этой теме http://stackoverflow.com/questions/3916608/how-important-is-standards-compliance - соответствие стандартам было бы замечательно для учащихся :))) –

0

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

+0

Я использовал компилятор g ++ – ameen

+0

Вы попробовали запустить программу? – casablanca

2

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

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

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

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

* О типичных архитектур

+0

Вы имеете в виду 4 ГБ памяти. –

+1

'UINT_MAX' обычно составляет около 4 миллиардов, а' int' - 4 байта. 4 миллиарда раз 4 байта - 16 ГБ. –

+0

@Peter: 'int' не обязательно 4 байта. – GManNickG

0

для каждого неподписанного интегрального типа максимум должен быть представлен -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 
Смежные вопросы