У массивов в C максимальный размер индекса составляет 2048? - PullRequest
2 голосов
/ 24 октября 2019

Я написал фрагмент кода, который использует статический массив размером 3000.

Обычно я бы просто использовал цикл for для сканирования 3000 значений, но, похоже, я могу сканировать только когда-либомаксимум 2048 номеров. Мне это кажется проблемой с распределением памяти, но я не уверен.

Проблема возникает из-за того, что я не хочу, чтобы пользователь вводил количество цифр, которое он намеревается ввести. Они должны вводить только то количество цифр, которое им нужно, прервать сканирование, введя 0, после чего программа выполняет свою работу. (В противном случае я бы просто использовал malloc.)

Код представляет собой довольно простой счетчик числа, найденный ниже:

int main(int argc, char **argv)
{

int c;
int d;
int j = 0;
int temp;
int array[3000];
int i;

// scanning in elements to array (have just used 3000 because no explicit value for the length of the sequence is included) 
for (i = 0; i < 3000; i++)
{
    scanf("%d", &array[i]);
    if (array[i] == 0)
    {
        break;
    }
}

// sorting
for(c = 0; c < i-1; c++)    { 
    for(d = 0; d < i-c-1; d++)  {
        if(array[d] > array[d+1])   { 
            temp        = array[d]; // swaps
            array[d]    = array[d+1];
            array[d+1]  = temp;
        }
    }
}

int arrayLength = i + 1; // saving current 'i' value to use as 'n' value before reset

for(i = 0; i < arrayLength; i = j)
{
    int numToCount = array[i];
    int occurrence = 1; // if a number has been found the occurence is at least 1
    for(j = i+1; j < arrayLength; j++) // new loops starts at current position in array +1 to check for duplicates
    {
        if(array[j] != numToCount) // prints immediately after finding out how many occurences there are, else adds another
        {
            printf("%d: %d\n", numToCount, occurrence); 
            break; // this break keeps 'j' at whatever value is NOT the numToCount, thus making the 'i = j' iterator restart the process at the right number
        } else {
            occurrence++;
        }
    }
}

return 0;
}

Этот код отлично работает для любого числа входов ниже 2048. Примером неработоспособности будет ввод: 1000 1 с, 1000 2 с и 1000 3 с, после чего программа выдаст:

1: 1000
2: 1000
3: 48

Мой вопрос: есть ли способ исправить это так, чтобы программавыведет правильное количество вхождений.

1 Ответ

3 голосов
/ 24 октября 2019

Чтобы ответить на ваш заглавный вопрос: размер массива в C ограничен (теоретически) только максимальным значением, которое может быть представлено переменной size_t. Обычно это 32-разрядное или 64-разрядное целое число без знака, поэтому вы можете иметь (для 32-разрядного случая) более 4 миллиардов элементов (или гораздо больше в 64-разрядных системах).

ОднакоТо, что вы, вероятно, встречаете в своем коде, - это ограничение памяти, доступной программе, где строка int array[3000]; объявляет автоматическую переменную. Пространство для них обычно выделяется в стеке - который является частью памяти ограниченного размера, доступной при вызове функции (или main). Эта память имеет ограниченный размер, и в вашем случае (при условии 32-разрядных 4-байтовых целых чисел) вы берете из стека 12 000 байт, что может вызвать проблемы.

Есть два (может быть, больше?)способы решить проблему. Во-первых, вы можете объявить массив static - это заставит компилятор предварительно выделить память, поэтому его не нужно будет извлекать из стека во время выполнения:

static int array[3000];

секунду,вероятно, лучше, если бы подходил вызов malloc для выделения памяти для массива;это назначает память из heap - которая имеет (почти на всех системах) значительно больше места, чем стек. Он часто ограничен только доступной виртуальной памятью операционной системы (много гигабайт на большинстве современных ПК):

int *array = malloc(3000 * sizeof(int));

Кроме того, преимущество использования malloc состоит в том, что если по какой-то причиненедостаточно памяти, функция вернет NULL, и вы можете проверить это. Вы можете получить доступ к элементам массива таким же образом, например, используя array[i]. Конечно, вы должны быть уверены, что освободите память, когда закончите с ней, в конце вашей функции:

free(array);

(Это будет сделано автоматически в вашем случае, когда программа выйдет,но это хороший стиль кодирования, чтобы привыкнуть делать это явно!)

...