Почему индексация начинается с нуля в '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. Я представил ответ на этот вопрос в диаграмме ниже, которую я написал на листе бумаги, который говорит само за себя
Основные шаги:
- Создание ссылки
- Создание массива
- Распределение данных в массив
- Также обратите внимание, когда массив только что создан... По умолчанию все блоки распределяются по нулям, пока мы не присвоим ему значение
- Массив начинается с нуля, потому что первый адрес будет указывать на ссылку (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.