Как адреса памяти знают, как долго массив? - PullRequest
0 голосов
/ 02 мая 2018

Полагаю, я могу пометить C ++, Assembly и C, поскольку управление памятью работает одинаково на всех языках.

Я только что вышел на сцену в Си, где я изучаю указатели. Я понимаю, что если вы храните строку (или в C, более известную как массив символов), это на самом деле просто адрес в памяти первого элемента этого массива.

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

Полагаю, я опубликовал это для проверки моего правильного ответа. Кто-нибудь может объяснить это поподробнее?

Ответы [ 4 ]

0 голосов
/ 02 мая 2018

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

[узкий] строковый литерал имеет тип char[C], где C == 1+strlen(s) (1 для '\0' в конце, который функция strlen исключает из возвращаемого значения).

Если вы храните строковый литерал в переменной типа char*, то это действительно так, как вы говорите: просто адрес в памяти первого элемента этого массива. Вот как работает «распад массива».

Если, однако, вы храните строковый литерал в переменной типа char[N], то как все будет работать, зависит от N и 1+strlen(S) (где S будет строковым литералом). Если N < 1+strlen(S), то в массиве char сохраняются только первые символы N, и массив не заканчивается на '\0'. Если N >= 1+strlen(S), то все символы S сохраняются в массиве char, а любые элементы, превышающие 1+strlen(S), инициализируются нулями, как обычно для массивов.

Как этот первый элемент массива знает, сколько он должен считать для всего массива я догадываюсь, что он останавливается при первом появлении \0 но я прав? Я Бен сказал \0 это признак того, что массив закончил, что вы нажали последний элемент (или технически, 1 после последний элемент).

Первый элемент не хранит счетчик массива, пока вы не сделаете это таким образом. В случае сохранения строкового литерала или любого другого массива char в объекте типа char*, вы отбрасываете информацию о размере, если вы не сохранили размер в первом элементе вручную (строки в языке программирования Pascal делают этот). Независимо от того, сохранили ли вы размер, вы все равно отвечаете за отслеживание информации о размере. Если вы инициализируете объект типа char[N] строковым литералом, вы сохраняете информацию о размере массива, и компилятор отслеживает все символы N в течение всего времени жизни массива.

0 голосов
/ 02 мая 2018

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

0 голосов
/ 02 мая 2018

Чтобы ответить на ваш вопрос, адреса памяти не «знают», какова длина массива. Все зависит от архитектуры вашего компьютера и обнаруживается с помощью инструкций процессора. Когда вы обращаетесь к первому элементу массива, ваш процессор декодирует инструкцию и продолжит захват первого байта данных в данном адресе памяти. Этот первый байт данных должен содержать значение ascii, которое относится к определенному элементу char и будет отображать желаемый символ. Если вы перебираете строку и правильно ее реализуете, обычно это нулевой символ, которым вы можете закончить итерацию. Тем не менее, обратите внимание, что нулевой символ не обязательно будет там.

0 голосов
/ 02 мая 2018

Это не так.

Используйте слишком большое значение в качестве индекса, и вы будете читать / записывать в память вне массива.

Сделайте это в C ++, и оптимизатор может кешировать данные, а не обновлять их и получать безумные состояния программы (UB).

Теперь скопируйте массив в структуру через =? Затем размер известен во время компиляции, так же как и не используются маркеры времени выполнения.

...