Какой максимальный размер массива в C? - PullRequest
43 голосов
/ 22 февраля 2012

Я понимаю, что аппаратное обеспечение будет ограничивать объем памяти, выделяемый во время выполнения программы.Тем не менее, мой вопрос без учета аппаратного обеспечения. Если предположить, что не было ограничений на объем памяти, не будет ли ограничений для массива?

Ответы [ 7 ]

41 голосов
/ 22 февраля 2012

Не существует фиксированного ограничения на размер массива в C.

Размер любого отдельного объекта, включая любой объект массива, ограничен SIZE_MAX,максимальное значение типа size_t, являющееся результатом оператора sizeof.(Не совсем ясно, разрешает ли стандарт C объекты размером более SIZE_MAX байт, но на практике такие объекты не поддерживаются; см. Сноску.) Поскольку SIZE_MAX определяется реализацией и не может быть изменен какой-либо программой, этонакладывает верхнюю границу SIZE_MAX байтов для любого отдельного объекта.(Это верхняя граница, а не в последнюю очередь верхняя граница; реализации могут и обычно накладывают меньшие ограничения.)

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

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

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

1025 * Удачи в поиске оборудования, которое на самом деле поддерживает такие объекты. 1027 *Сноска : Нет явного правила, согласно которому ни один объект не может быть больше SIZE_MAX байтов.Вы не могли бы с пользой применить оператор sizeof к такому объекту, но, как и любой другой оператор, sizeof может переполниться;это не значит, что вы не можете выполнять операции с таким объектом.Но на практике любая нормальная реализация сделает size_t достаточно большим, чтобы представить размер любого объекта, который она поддерживает.
8 голосов

C99 5.2.4.1 "Пределы перевода" минимальный размер

Реализация должна иметь возможность переводить и выполнять по крайней мере одну программу, которая содержит по крайней мере один экземпляр каждого из следующих ограничений: 13)

  • 65535 байт в объекте (только в размещенной среде)

13) Реализации должны по возможности избегать наложения фиксированных ограничений на перевод.

Это говорит о том, что соответствующая реализация может отказаться от компиляции объекта (который включает в себя массивы) с более чем short байтами.

PTRDIFF_MAX представляется практическим ограничением для статических объектов массива

Стандарт C99 6.5.6 Аддитивные операторы говорит:

9 Когда вычитаются два указателя, оба должны указывать на элементы одного и того же объекта массива, или один за последним элементом массива объекта; Результатом является разница индексы двух элементов массива. Размер результата определяется реализацией, и его тип (целочисленный тип со знаком) ptrdiff_t определен в заголовке <stddef.h>. Если результат не может быть представлен в объекте этого типа, поведение не определено.

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

Так что, возможно, по этой причине GCC, похоже, ограничивает вас ptrdiff_t. Это также упоминается в: Почему максимальный размер массива слишком велик?

Я эмпирически подтвердил это с помощью main.c:

#include <stdint.h>

uint8_t a[(X)];

int main(void) {
    return 0;
}

и затем в Убунбу 17.10:

$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ printf '
> #include <stdint.h>
> PTRDIFF_MAX
> SIZE_MAX
> ' | arm-linux-gnueabi-cpp | tail -n2
(2147483647)
(4294967295U)
$ PTRDIFF_MAX == 2147483647 == 2^31 - 1
$
$ # 2lu << 30 == 2^31 == PTRDIFF_MAX + 1
$ arm-linux-gnueabi-gcc -std=c99 -DX='(2lu << 30)' main.c
a.c:5:9: error: size of array ‘a’ is too large
 uint8_t a[(X)];
         ^
$
$ # PTRDIFF_MAX
$ arm-linux-gnueabi-gcc -std=c99 -DX='(2lu << 30) - 1lu' main.c
$

См. Также

6 голосов
/ 22 февраля 2012

64-битная машина теоретически может адресовать максимум 2 ^ 64 байта памяти.

4 голосов
/ 22 февраля 2012

Без учета памяти максимальный размер массива ограничен типом целого числа, используемого для индексации массива.

2 голосов
/ 22 февраля 2012

Размер указателя ограничит доступ к памяти. Даже если аппаратное обеспечение поддерживает неограниченную память, если самый большой тип данных, который вы можете использовать, является 64-битным, вы сможете получить доступ только к 2 ^ 64 байтам памяти.

2 голосов
/ 22 февраля 2012

Я полагаю, что самым большим теоретическим массивом будет максимальное значение "unsigned long" (или любое большее целое число, которое поддерживает последний стандарт / ваш компилятор)

0 голосов
/ 11 сентября 2013

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

Изначально C не предоставляет никакой функции для определения максимального количества элементов, выделяемых в массиве во время компиляции. Это потому, что это будет зависеть от объема памяти, доступной на компьютере, где он будет выполняться.

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...