Как модель памяти с++ определяет тип данных?

Когда мы компилируем код

int i = 0;

Компилятор присваивает вместо переменной i какой то адрес в памяти (начальную ячейку) и далее работает с ней например считывает из нее данные. У меня вопрос

  1. Как при чтении компилятор понимает что нужно прочитать именно 4байта (int) ведь тип данных не храниться на сколько я знаю, а передаем мы ему только начальный адрес.
  2. Как это работает если по адресу у нас лежит не int, а длинная строка или какой либо динамический тип который может увеличиваться, получается конец данных будет постоянно смещаться отодвигая все что записано за ним?

Ответы (3 шт):

Автор решения: Roman Konoval

Это в скомпилированной программе нет (явной) информации о длине int. А во время компиляции компилятор то знает, что i типа int и значит у нее определенная длина. А значит при чтении нужно читать 4 байта (если длина int именно 4 байта).

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

Компилятор об этом "не знает" в том смысле, что он ничего специального не делает. Это сама программа обращается только в рамках строки, т.е. например, делает цикл от начала, т.е. от байта на который указывает указатель на начало строки, и пока не встретит нулевой байт. Компилятор знает тип "указатель на байт" и в обращениях к элементам вставляет код, который, скажем, читает байт по указателю (тут длина строки никак не участвует). То что под строку выделено, скажем, 10 байт, компилятор не знает.

→ Ссылка
Автор решения: Harry

Как при чтении компилятор понимает что нужно прочитать именно 4байта (int) ведь тип данных не храниться на сколько я знаю, а передаем мы ему только начальный адрес.

Компилятор, который компилирует исходный код, знает об этом — потому что знает, что переменная объявлена как int, а размеры типов ему известны. Так что он сгенерирует правильный код? который и будет перемещать 4 байта куда надо.

Как это работает если по адресу у нас лежит не int, а длинная строка или какой либо динамический тип который может увеличиваться, получается конец данных будет постоянно смещаться отодвигая все что записано за ним?

Вопрос, как бы сказать... как по мне, некорректен. Если там лежит строка — то будет сгенерирован код для работы со строкой (с проверкой, например, завершающего нулевого символа etc). Динамический тип — что именно вы имеете в виду? Какой-нибудь вектор? Но при присваивании одного вектора другому не будет простой инструкции переноса из одного места памяти в другое, как и при копировании строки, например. Это будет целый ряд простых команд процессора, целая своя подпрограмма. Так что коду не надо знать о размере такого меняемого во время работы объекта — он просто тем или иным способом будет вычислен.

"По-моему, так" (с) Пух

→ Ссылка
Автор решения: Илья К
  1. Каждый компилятор сам решает сколько байтов в int. Выбирая компилятор ты автоматически соглашаешься с его "мнением", вот к примеру мнение Компиляторы Microsoft C++. Во время компиляции компилятор выбирает команды соответствующие заранее оговоренной размерности.

  2. Что касается твоего вопроса о различии при чтении строки и int, так их чтение с точки зрения машинной логики ничем не отличается, при работе со строками они также читаются по одному символу за раз, за исключением случаем когда при помощи специализированного сета intrinsics предусмотрена их обработка по 16/32/64 байта за раз.

  3. При чтении строки дополнительно предусматривается проверка символа на значение NULL которое означает конец строки, столкнувшись с таким символом "нормальны" код завершит обработку строки, а "кривой" продолжит читать всю оставшуюся память пока не превысит права доступа к памяти и программа не упадет, со словами "инструкция ХХХ обратилась к памяти ХХХ, которая не может быть READ".

→ Ссылка