Как компьютеры различают 2 части данных? [закрытый]
Мне было интересно, что компьютеры хранят всю информацию в виде 1s и 0s / low и high voltage, yada yada...но затем, когда мы компилируем программу, она - или просто любые данные, хранящиеся на компе-находится в двоичной форме...тогда как же компьютер различает 2 части данных, так как все, что он состоит из потока 0s и 1s...To чтобы сделать мой вопрос более ясным, давайте возьмем смехотворно простой код из C:
void main() {
int A = 0;
int* pA = &A;
char c = 'c';
char* pC = &c;
return;
}
Он ничего не делает - просто делает 4 переменные типов int, указатель на Int, char и указатель на Char...Теперь они будут храниться где-то в виде 0s и 1s...So, как компьютер узнает, с какого бита начинается такая-то переменная и где она заканчивается? Для начала вы можете сказать, что компьютер имеет его адрес, хорошо, согласен. Но как насчет конца?...А как насчет сложных типов данных, таких как объекты / структуры?
И последнее, но не менее важное: как насчет функций / процедур?6 ответов:
Абзац, который вы сейчас читаете, - это не что иное, как поток букв и знаков препинания. Как узнать, где начинается и заканчивается одно слово? Откуда ты знаешь, ЧТО означают эти слова? Как этот поток текста передает полезную информацию?
То же самое можно сказать и о математике. Когда вы видите математические выражения, написанные на странице, они представляют собой просто ряд чисел и символов, но они являются мощным способом передачи глубоких идей в компактной форме. А потом-музыка. Как представляет ли этот поток точек, флагов и линий нечто столь же преходящее, как музыка? Ответ, конечно, заключается в том, что существуют правила. Буквы не просто комбинируются случайным образом-они имеют определенную последовательность. Когда вы следуете правилам, которые мы оба знаем, вы можете различать слова, понимать их индивидуальные значения и объединять их в мысли.То же самое и с двоичными данными. Единственное, что отличает данные от случайных битов, - это наличие правил. это, если следовать, позволит толковать биты осмысленным образом. Итак, вы задали много вопросов, которые связаны с различными правилами. Попытка объяснить их все заняла бы больше места, чем разумно в ответе, подобном этому (и больше времени, чем я готов посвятить этому начинанию). Но если вы возьмете книгу по компьютерной архитектуре, вы найдете полное обсуждение правил, как они работают, как они организованы и как они реализуются. Это действительно интересно чепуха!
Если вы еще не готовы погрузиться в настоящую компьютерную архитектуру, одна превосходная книга, которая даст вам много понимания, - это Godel, Escher, Bach: an Eternal Golden Braid Дугласа Хофштадтера. Это толстая книга, полная идей. Но она также хорошо написана и интересна, и вам не обязательно читать ее от корки до корки, чтобы узнать много интересного.
Вы можете ответить на все эти вопросы(и еще на многие относительно компьютеров), подойдя как можно ближе к металлу:то есть, изучите сборку.Я предлагаю прочитать книгуArt of Assembly (в свободном доступе в интернете), которая также охватывает эти темы. Кроме того, прочитайте мой ответ на ресурсы обучения сборке.Теперь позвольте мне кратко ответить на ваши вопросы:
Вы правы в том, что компьютер видит только бесконечный поток битов.Операционная система выполняет эту работу. о создании файловой системы.Даже оперативную память можно рассматривать как очень простую файловую систему (с файлами в виде страниц или сегментов).Теперь это означает, что у ОС есть таблица, где она отслеживает, где каждая программа хранит то,что, что такое данные, что такое код и т. д.
- Переменные на фундаментальном уровне - это не более чем байты.Теперь, когда вы пишете заявление, такое как
A = b + 1
Компилятор фактически присваивает произвольный адрес переменные и жесткие коды (то есть записывает фактическую константу, например 0xA3F0) этот адрес для каждого оператора, который ссылается на него.
Более того, современные архитектуры не позволяют ОС делать все это самостоятельно.Большая часть домашнего хозяйства происходит и на аппаратном уровне, например, управление памятью, маркировка того, какой адрес памяти служит какой цели и т. д.
Структуры данных хранятся различными способами.Однако, когда мы говорим о структурах c, все проще: они просто хранят переменные, которые эта структура содержит одну за другой, если мы игнорируем такие вещи, как заполнение и т. д.Вот почему длина структуры всегда известна.
Функции на самом деле являются местами в памяти где находится код stored.To "вызов" функции, аргументы загружаются в стек или любое другое глобальное пространство памяти, а затем выполняется переход, т. е. goto, к адресу функции.когда функция выполнена, она переходит к адресу, который вызвал ее (адрес также хранится в стеке.)
Важно понимать, что компилятор выполняет всю тяжелую работу по переводу вашего кода вышеупомянутыми способами.Все функции, которые есть у языков высокого уровня, - это просто абстракции для того, чтобы сделать вашу работу easier.In конец, однако, это просто биты и байты, 0s и 1s, 5 вольт и ноль вольт.
Одна и та же последовательность битов может быть интерпретирована как числа, строки, код, структуры, что угодно. Компьютер не имеет никакого способа узнать, какой должна быть связка битов.
Попробуйте это:
int main() { int A = 0; char* pC = (char*)&S; }
Вы увидите, что это работает. Он берет целочисленную память и говорит, что я хочу рассматривать ее как массив символов. Компьютер с радостью согласится с этим. Это редко бывает полезно, но это можно сделать.
Единственное, что отличается для разных типов, - это то, как они лечатся. Поплавки обрабатываются иначе, чем целые числа, обрабатываются иначе, чем строки. Если вы посмотрите на низкоуровневую версию вашей программы, вы обнаружите, что каждая операция включает в себя определенный тип данных. Разница не в битах, а в том, как программа работает с битами.
Компьютер не знает, и компьютер не заботится. Все, что он делает, это следует инструкциям. Одна из таких команд может сказать:"Возьмите 32 бита из этого адреса и еще 32 бита из этого адреса; объедините эти две 32-разрядные строки с помощью метода, называемого "сложение дополнения двух"; и сохраните результат в 32 битах по первому указанному адресу". Каждая инструкция определяет:
Адрес(адреса), с которого (ов) будут считываться данные и на который (ов) будут передаваться данные. написано
Число битов для чтения или записи
Операция, выполняемая над битами read
Компьютеру все равно, что делает операция. Просто компьютерный конструктор был достаточно хорош, чтобы сделать эту операцию полезной для нас, людей.
Программа, подобная той, которую вы даете, в очень реальном смысле находится навысоком уровне . Требуется перевод, чтобы создать форму, которую компьютер может понять. Такой переводчик знает, что такое
Таким образом, вы почти ответили на свой собственный вопрос:int
, Что такоеint *
, и знает, сколько битов они принимают в память и какие компьютерные операции могут быть с пользой применены к ним.Конец известен, если вы знаете начало и длину. Более сложные структуры данных обычно состоят из отдельных, более простых частей. Так, при переводе такого кода Вы берете детали, назначаете им смещения, следя за тем, чтобы ни одна деталь не перекрывала другую, а затем используете смещения для вычисления адреса, используемого для доступа к деталям. Процедуры и функции слишком сложны, чтобы их можно было здесь объяснить.Для начала вы можете сказать, что компьютер имеет его адрес, хорошо, согласен. Но как насчет конца?
Но короткая заметка в конце о вашем примере программы. Как вы говорите, это ничего не дает. Умный переводчик просто напишет инструкцию" ничего не делать " компьютеру. Менее умный переводчик будет назначать адреса каждую из переменных вы объявляете и записываете две инструкции: "зарезервируйте место для этого количества битов; а затем ничего не делайте" (количество битов-это длина пространства, необходимого для хранения каждой из переменных). Ни в коем случае компьютер не должен ничего знать о переменных в вашей программе.
Скомпилированная программа будет состоять из машинных инструкций, которые обращаются к данным в шаблонах, отражающих типы высокого уровня. Большинство языков ассемблера имеют различные инструкции для загрузки и манипулирования данными различных размеров (загрузка байтов, слов, лонгов и т. д.).) или типы (целые числа со знаком и без знака, плавающие и длинные числа и т. д.). Поскольку компилятор имеет информацию о типе, доступную ему во время компиляции, он может выдавать инструкции по сборке, которые обрабатывают данные в памяти, и это все только нули и единицы, как имеющие соответствующую структуру путем выдачи команд для работы с данными таким образом, который согласуется с системой типов.
Для структур и функций существует множество возможных кодировок в зависимости от используемого языка. Прошлым летом я читал курс компиляторов, и мы провели две лекции о макетах функций и объектов. Слайды для первой и второй лекций доступны по предыдущим ссылкам.
Надеюсь, это поможет!
Написание на языке высокого уровня правил языка и компилятор встраивают эту информацию в созданную программу. Процессору / процессору было бы все равно, что это просто биты, они не имеют никакого значения, кроме как в течение очень короткого периода времени, когда выполняется команда. Для инструкции add биты являются операндами для сложения или результата, для загрузки или хранения они могут быть адресом или смещением к адресу и т. д., Но сразу после этого возвращаются к бессмысленности биты.
Как упоминалось в другом сообщении, эти слова, которые Вы читаете, являются просто комбинациями букв из алфавита и не имеют никакого значения, взятые по одному, не имеют никакого значения для веб-браузера или видеокарты, отображающей пиксели, но для пользователя высокого уровня они имеют значение. То же самое с программами, уменьшите немного, посмотрите на программу в целом, и вы увидите, что комбинации инструкций и битов образуют последовательности программ, которые реализуют типы переменных и высокие значения. последовательности программ уровня, которые вы написали и скомпилировали.
В этом нет никакой магии