Почему индексация начинается с нуля в 'C'?

Почему индексация в массиве начинается с нуля в C, а не с 1?

13 ответов

В C имя массива по сути является указателем, ссылкой на ячейку памяти, и поэтому массив выражений [n] ссылается на n-элементы ячейки памяти вдали от начального элемента. Это означает, что индекс используется в качестве смещения. Первый элемент массива точно содержится в ячейке памяти, на которую ссылается массив (0 элементов), поэтому он должен быть обозначен как массив [0].

для получения дополнительной информации:

http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html

Этот вопрос был опубликован более года назад, но здесь идет...


О вышеуказанных причинах

Хотя статья Дейкстры (ранее упоминавшаяся в уже удаленном ответе) имеет смысл с математической точки зрения, она не так актуальна, когда речь идет о программировании.

Решение, принятое спецификаторами языка и разработчиками компиляторов, основано на решении разработчиков компьютерных систем начать отсчет с 0.


Возможная причина

Цитата из " Просьбы о мире " Дэнни Коэна.

Для любого основания b первые неотрицательные целые числа b^N представлены ровно N цифрами (включая ведущие нули), только если нумерация начинается с 0.

Это можно проверить довольно легко. В базу-2 возьмите 2^3 = 8Восьмой номер:

  • 8 (двоичный код: 1000), если мы начнем считать с 1
  • 7 (двоичный код: 111), если мы начнем считать с 0

111 может быть представлен с помощью 3 биты, а 1000 потребуется дополнительный бит (4 бита).


Почему это актуально

Адреса памяти компьютера имеют 2^N ячейки адресованы N биты. Теперь, если мы начнем считать с 1, 2^N клетки понадобятся N+1 адресные строки. Дополнительный бит необходим для доступа ровно к 1 адресу. (1000 в приведенном выше случае.). Другой способ решить эту проблему - оставить последний адрес недоступным и использовать N адресные строки.

Оба являются неоптимальными решениями, по сравнению с начальным счетом в 0, который будет держать все адреса доступными, используя точно N адресные строки!


Заключение

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


Цитата из статьи:

Потому что 0 это расстояние от указателя на начало массива до первого элемента массива.

Рассматривать:

int foo[5] = {1,2,3,4,5};

Для доступа к 0 мы делаем:

foo[0] 

Но foo разлагается на указатель, и вышеупомянутый доступ имеет аналогичный указатель арифметического способа доступа к нему

*(foo + 0)

В наши дни арифметика указателей используется не так часто. Еще тогда, когда это был удобный способ взять адрес и убрать X "целых" из этой начальной точки. Конечно, если вы хотите просто остаться на месте, просто добавьте 0!

Поскольку индекс на основе 0 позволяет...

array[index]

... быть реализованным как...

*(array + index)

Если бы индекс был основан на 1, компилятору нужно было бы сгенерировать: *(array + index - 1)и это "-1" повредит производительности.

Потому что это сделало компилятор и компоновщик проще (легче писать).

Ссылка:

"... Ссылка на память по адресу и смещению представлена ​​непосредственно в аппаратном обеспечении практически на всех компьютерных архитектурах, поэтому эта деталь конструкции в C упрощает компиляцию"

а также

"... это упрощает реализацию..."

По той же причине, что, когда наступает среда, и кто-то спрашивает вас, сколько дней до среды, вы говорите 0, а не 1, а когда это среда, и кто-то спрашивает вас, сколько дней до четверга, вы говорите 1, а не 2.

Индекс массива всегда начинается с нуля. Предположим, базовый адрес равен 2000. Теперь arr[i] = *(arr+i), Сейчас if i= 0, это означает *(2000+0) равен базовому адресу или адресу первого элемента в массиве. этот индекс обрабатывается как смещение, поэтому индекс по умолчанию начинается с нуля.

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

Основные шаги:

  1. Создание ссылки
  2. Создание массива
  3. Распределение данных в массив

  • Также обратите внимание, когда массив только что создан... По умолчанию все блоки распределяются по нулям, пока мы не присвоим ему значение
  • Массив начинается с нуля, потому что первый адрес будет указывать на ссылку (i:e - X102+0 на изображении)

Примечание: блоки, показанные на изображении, являются представлением памяти

Это потому, что address должен указывать вправо elementв массиве. Предположим, что следующий массив:

let arr = [10, 20, 40, 60]; 

Давайте теперь рассмотрим, как начинается адрес 12 и размер element быть 4 bytes.

address of arr[0] = 12 + (0 * 4) => 12
address of arr[1] = 12 + (1 * 4) => 16
address of arr[2] = 12 + (2 * 4) => 20
address of arr[3] = 12 + (3 * 4) => 24

Если бы не было zero-based, технически адрес нашего первого элемента в array было бы 16 что неверно, так как это местоположение 12.

Самым элегантным объяснением, которое я прочитал для нумерации с нуля, является наблюдение, что значения хранятся не в отмеченных местах на числовой строке, а в промежутках между ними. Первый элемент сохраняется от нуля до единицы, следующий - от одного до двух и т. Д. N-й элемент сохраняется от N-1 до N. Диапазон элементов может быть описан с использованием чисел с обеих сторон. Отдельные предметы по договоренности описываются с помощью номеров под ними. Если каждому дан диапазон (X,Y), идентификация отдельных чисел с использованием числа, указанного ниже, означает, что можно идентифицировать первый элемент без использования какой-либо арифметики (это элемент X), но нужно вычесть один из Y, чтобы идентифицировать последний элемент (Y-1). Идентификация предметов с использованием числа, указанного выше, облегчит идентификацию последнего элемента в диапазоне (это будет элемент Y), но сложнее определить первый (X+1).

Хотя было бы не страшно идентифицировать предметы, основываясь на числе над ними, определение первого предмета в диапазоне (X, Y) как того, что выше X, обычно получается более приятным, чем определение того, что ниже (X +). 1).

Предположим, мы хотим создать массив размером 5
массив int [5] = [2,3,5,9,8]

пусть 1-й элемент массива направлен в точку 100

и пусть мы рассмотрим индексацию, начинающуюся с 1, а не с 0.

Теперь мы должны найти местоположение 1-го элемента с помощью индекса
(помните, что расположение 1-го элемента - 100)

так как размер целого числа 4-битный
поэтому -> с учетом индекса 1 позиция будет
размер индекса (1) * размер целого числа (4) = 4
поэтому фактическая позиция покажет нам

100 + 4 = 104

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

Теперь предположим, что мы взяли индексацию от 0
затем
позиция 1-го элемента должна быть
размер индекса (0) * размер целого числа (4) = 0

поэтому ->
расположение 1-го элемента 100 + 0 = 100

и это было фактическое местоположение элемента
вот почему индексация начинается с 0;

Я надеюсь, что это прояснит вашу точку зрения.

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

Попробуйте получить доступ к пиксельному экрану, используя координаты X,Y на основе матрицы 1. Формула очень сложная. Почему это сложно? Поскольку вы в конечном итоге преобразуете координаты X,Y в одно число - смещение. Зачем вам нужно конвертировать X,Y в смещение? Потому что так организована память внутри компьютеров, как непрерывный поток ячеек памяти (массивов). Как компьютеры работают с элементами массива? Использование смещений (смещения из первой ячейки, модель индексации с нуля).

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

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

Прежде всего вам нужно знать, что массивы внутренне рассматриваются как указатели, потому что "имя самого массива содержит адрес первого элемента массива"

ex. int arr[2] = {5,4};

Предположим, что массив начинается с адреса 100, поэтому первый элемент элемента будет по адресу 100, а второй теперь будет по адресу 104. Учтите, что если индекс массива начинается с 1, то

arr[1]:-

это может быть записано в выражении указателей как это-

 arr[1] = *(arr + 1 * (size of single element of array));

рассмотрим размер int 4 байта, теперь,

arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);

как мы знаем, имя массива содержит адрес его первого элемента, поэтому теперь arr = 100,

arr[1] = *(100 + 4);
arr[1] = *(104);

который дает,

arr[1] = 4;

из-за этого выражения мы не можем получить доступ к элементу по адресу 100, который является официальным первым элементом,

Теперь рассмотрим индекс массива, начинающийся с 0, поэтому

arr[0]:-

это будет решено как

arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);

теперь мы знаем, что имя массива содержит адрес его первого элемента, поэтому

arr[0] = *(100);

который дает правильный результат

arr[0] = 5;

поэтому индекс массива всегда начинается с 0 в c.

справка: все подробности написаны в книге "Язык программирования С Брайана Кернингхана и Денниса Ричи"

Имя массива - это постоянный указатель, указывающий на базовый адрес. Когда вы используете arr[i], компилятор обрабатывает его как *(arr+i). Поскольку диапазон int равен от -128 до 127, компилятор считает, что от -128 до -1 отрицательные числа и от 0 до 128 являются положительными числами. Поэтому индекс массива всегда начинается с нуля.

becoz, когда мы получаем доступ к элементам массива, следующая формула используется компилятором ((базовый адрес)+ индекс * размер). Элемент fisrt всегда хранится по базовому адресу в массивах... Так что, если мы начнем с 1, мы не сможем получить доступ к первому элементу, так как он дает адрес элемента sesond... поэтому он начинается с 0.

Другие вопросы по тегам