Данному образовательному сайту пришлось несколько раз менять свое имя. С 2022 года доступ к нему обеспечивается по URL
emc.km.ru (2001-2007) ==> educomp.org.ru (2007-2011) ==> educomp.runnet.ru (2011-2021) ==> emc.orgfree.com (2022-...)
Более подробно об истории сайта можно прочитать здесь.
|
Представление различных типов данных в Турбо ПаскалеКак известно, одним из важных вопросов информатики является представление информации в ЭВМ. Именно с этой точки зрения автор предлагает сегодня взглянуть на различные типы данных, имеющиеся в языке Паскаль. В статье описано, в каких формах может Паскаль хранить в ОЗУ числовую и текстовую информацию, как она объединяется в более сложные типы данных (строки, массивы, записи), а также как представляются более специализированные виды информации, такие как перечисление, множество и другие. Проведенное рассмотрение убедительно подтверждает фундаментальный тезис о том, что любая информация в ЭВМ имеет двоичное представление, а также позволяет познакомиться с существующими способами кодирования информации. Изложенные в статье сведения тщательно сверены с официальным руководством по Паскалю фирмы Borland [1] и проверены экспериментально. Вместе с тем автор старался, чтобы статья была интересна не только с точки зрения программирования на Паскале, но и как описание современных принципов хранения информации в ЭВМ. Если это удалось, о чем судить предоставляю возможность читателям, материал будет полезен всем преподавателям информатики, а также тем, кто хотел бы поглубже изучить этот современный и динамически развивающийся предмет. В качестве помощника в изучении представления информации в памяти ЭВМ мы возьмем несложную программу на языке Паскаль, которую назовем DATA EXPLORER - ИССЛЕДОВАТЕЛЬ ИНФОРМАЦИИ. Ее полный, достаточно короткий текст приводится ниже.
PROGRAM DataExlorer(input,output); CONST DataLen=2; {количество байт} TYPE exp=integer; {исследуемый тип} VAR s,o,i:integer; {рабочие переменные} e:exp; {исследуемая переменная} FUNCTION HexPrint(n:integer):string; {16-ричный вывод байта} VAR d,j:integer; r:string[4]; {рабочие переменные} BEGIN r:=''; FOR j:=1 TO 2 DO BEGIN d:=n and $f; {лог. И: выделить последнюю цифру} IF d<10 THEN r:=chr(ord('0')+d)+r {'0'..'9'} ELSE r:=chr(ord('A')+d-10)+r; {'A'..'F'} n:=n shr 4; {сдвиг: подготовить следующую цифру} END; HexPrint:=r END; BEGIN writeln; e:=1; {придать значение исследуемой переменной} s:=seg(e);o:=ofs(e); {получить адрес переменной в ОЗУ} {напечатать содержимое DataLen байт ОЗУ} FOR i:=0 TO DataLen-1 DO writeln(HexPrint(mem[s:o+i])); readln; END. Текст подробно прокомментирован, но несколько слов по поводу устройства Data Explorer все же следует сказать. Чтобы исследовать некоторый тип данных, необходимо внести сведения о нем в текст программы. Константа DataLen и тип exp определят требуемый размер памяти и исследуемый тип данных. Дополнительно потребуется задавать интересующее Вас значение изучаемой переменной e. Примечание. Казалось бы, удобнее значение e вводить с клавиатуры, а не изменять каждый раз оператор присвоения в программе. Но на самом деле для многих типов данных в Паскале ввод с клавиатуры запрещен! Программа определяет адрес переменной e в ОЗУ (сегмент s и
смещение o) и выводит на экран ее содержимое. Для вывода на экран байта ОЗУ в шестнадцатиричном виде используется функция HexPrint.
Примечание.Если вы захотите воспользоваться этой программой в Delphi, у вас возникнут трудности. О способе их преодоления можно почитать здесь.
Имея такой довольно мощный инструмент исследования, как Data Explorer, мы можем смело начинать подробное рассмотрение типов данных. Представление числовых данных в Паскале: типы INTEGER, REAL и другиеВсем известно, что ЭВМ первоначально предназначалась для обработки только числовой информации, о чем убедительно свидетельствует данное ей название. Неудивительно, что числовые типы данных появились в языках программирования в первую очередь и к настоящему времени практически стандартизировались. Наиболее "старыми" являются числовые типы INTEGER (целые) и REAL (вещественные). Наличие двух базовых типов чисел объясняется целым рядом причин, причем то, что такого рода деление существует в математике, далеко не самое главное. Гораздо важнее, что обходиться на ЭВМ только вещественными числами, объявив целые частным случаем, практически невозможно. Дело в том, что из-за ограниченности количества разрядов вещественные числа в машине не могут быть представлены абсолютно точно. В ходе длинных вычислений это неудобство становится еще более заметно. Например, если 10 раз сложить значение 0,1 , результат окажется чуть-чуть отличным от 1. Не верите? Запустите на Турбо Паскале простейшую программу:
PROGRAM paradox; VAR x,y:REAL; i:INTEGER; BEGIN x:=1; y:=0; FOR i:=1 TO 10 DO y:=y+0.1; IF x=y THEN writeln('x равно y') ELSE writeln('x не равно y'); writeln('разность x и y равна', x-y); END. Как ни странно, она напишет, что x не равно y! Такое "поведение" чисел достаточно неудобно, так как для многих объектов количество должно быть в точности целым (как тут не вспомнить известный детский мультфильм про полтора землекопа!) Кроме того, такие объекты есть и в самой ЭВМ - адреса ОЗУ, значения счетчиков циклов и некоторые другие. Если добавить, что для хранения целого числа требуется в несколько раз меньше памяти, то станет понятно, почему целочисленные переменные в программах обычно используются даже чаще, чем вещественные. Все это вместе взятое приводит к тому, что INTEGER и REAL гармонично уживаются во всех языках программирования, подобно белым и черным клавишам на пианино. Рассмотрение представления чисел удобнее начать с более простых - целых. В любой книге по устройству ЭВМ (см., например, [2,3]; много интересных сведений о внутреннем представлении чисел можно также найти в недавних публикациях журнала "Информатика и образование" [4,5]) Вы можете прочесть, что целые числа хранятся в памяти в двоичном виде и разобрать способы перевода десятичных чисел в двоичную систему и наоборот. Поэтому здесь мы ограничимся примером представления отрицательного числа, чему внимания обычно уделяется гораздо меньше. Для получения двоичного кода отрицательного числа (в литературе его обычно называют дополнительным кодом) необходимо выполнить две несложные операции:
Проверим сформулированное правило на примере числа -256. Число 25610 = 010016 = 0000 0001 0000 00002 проинвертируем: В качестве закрепления рекомендую самостоятельно повторить данную процедуру для результирующего двоичного кода. Если Вы нигде не ошибетесь, то получите исходное число, так как -(-256) = 256.
Примеры внутреннего представления некоторых характерных целых чисел, записанные в шестнадцатиричной системе, приведены в таблице 1. Внимательно ознакомьтесь с ней и обратите внимание на следующие моменты.
Примечание. Во всех имеющихся в статье таблицах при записи полного представления числа образующие его байты стоят в порядке старшинства, как это принято в математике, а не в том порядке, в каком они хранятся в оперативной памяти! Например, у кода 7FFF байт FF хранится первым, а за ним следует 7F. Помимо INTEGER, в Турбо Паскале существует несколько других целочисленных типов данных: SHORTINT, LONGINT, а также BYTE и WORD. Их основные характеристики приведены в таблице 2.
Особенно важно, что типы BYTE и WORD отличаются от остальных отсутствием отрицательных значений. Такие типы принято называть беззнаковыми. Сравним, например, INTEGER и WORD. Из таблицы 2 следует, что количество допустимых значений для этих 16-разрядных данных одинаково, но диапазон различен. Кроме того, разное представление рассматриваемых типов приводит к неодинаковому порядку следования шестнадцатиричных кодов: сравните таблицы 1 и 3.
Займемся теперь вещественными числами. Как известно, их главное отличие состоит в существовании двух частей - целой и дробной, разделяемых при записи запятой. Заметим, что в англоязыких странах в качестве разделителя принята точка: именно поэтому в Паскале число "полтора" будет выглядеть как 1.5 . Как перейти от целых чисел к вещественным? Можно, например, зафиксировать положение запятой между двумя определенными соседними разрядами - такой подход носит название чисел с фиксированной запятой. Реализация арифметики в этом случае получается очень простая, но она обладает существенным недостатком - малым диапазоном допустимых значений: числа с большой целой частью равно как и числа много меньше единицы "не помещаются" на фиксированную разрядную сетку. В качестве более удобного решения существует альтернативный способ представления вещественных чисел - с плавающей запятой. Он основан на том факте, что любое число A в системе счисления с основанием Q можно записать в виде где M называют мантиссой, а показатель степени P - порядком числа. Для десятичной системы это выглядит очень привычно, например: заряд электрона равен -1,6*10-19 к, а скорость света составляет 3*108 м/сек. Представление числа с плавающей запятой не является единственным: Поэтому договорились для выделения единственного варианта записи числа считать, что мантисса всегда меньше единицы, а ее первый разряд содержит отличную от нуля цифру - в нашем примере этим требованиям удовлетворит только число 0,3*109. Описанное представление чисел называется нормализованным и является единственным. Любое число может быть легко нормализовано. Все сказанное можно применять и к двоичной системе: Например: -310 = -0,11*210: M=0,11 и P=10. Арифметика чисел с плавающей запятой оказывается заметно сложнее, чем с фиксированной. Например, чтобы сложить два таких числа требуется предварительно привести их к представлению, когда оба порядка равны; такую процедуру принято называть выравниванием порядков. Кроме того, в результате сложения часто нарушается нормализация, а значит необходимо ее восстанавливать. Тем не менее вычислительные машины со всем этим великолепно умеют автоматически справляться и именно такой способ лежит в основе работы современных компьютеров. Казалось бы, теперь достаточно выяснить, сколько разрядов и какие отведены под мантиссу и порядок, и все станет на свои места. Но не тут-то было! Запустив DATA EXPLORER с DataLen=6 [1], получим не совсем понятное содержимое ОЗУ, приведенное во второй колонке таблицы 4:
Чтобы расшифровать полученные результаты, необходимо к уже известным нам сведениям о мантиссе и порядке добавить еще три [1]:
Чтобы разобраться во всех этих сложностях, возьмем для примера число 5 из первой строки таблицы. Его первый байт хранит закодированное значение порядка. Нетрудно видеть, что P=83-80=3. Оставшиеся байты мантиссы расшифровать несколько сложнее. С учетом того, что младшие байты лежат в ОЗУ раньше (число хранится "задом наперед"), получим Сравнив с числом -5, увидим, что старший разряд знаковый: в нашем случае он равен 0, т.к. 5>0. Собственно на мантиссу без знака остается Наконец, восстановив "скрытую единицу", окончательно получим значение мантиссы: Поскольку P=3, расшифровываемое число имеет окончательный вид Обратите также внимание на то, что отрицательная мантисса не преобразуется в дополнительный код, поэтому она отличается от таковой для положительного числа только в знаковом разряде. Завершая разговор о представлении вещественных чисел в Паскале, отметим, что в современных его версиях есть еще несколько таких типов данных: SINGLE, DOUBLE, EXTENDED и COMP. Их основные характеристики приведены в таблице 5 (по данным [1]).
Наверное, Вы уже изрядно утомлены техническими деталями и не захотите разбираться в тонкостях новых вещественных типов данных. Хорошо, мы не будем их обсуждать. Позволю себе только привести в заключение цитату из книги о самой современной версии компилятора с языка Паскаль - Delphi: "Delphi не допускает старого типа с плавающей точкой Real в качестве типа опубликованного свойства. Вы должны использовать новые типы: Single, Double, Extended, Comp или Currency. Фактически вы должны использовать новые свойства, поскольку они более гибки и более эффективны по сравнению с Real. Real существует только для обратной совместимости с предыдущими версиями Pascal." [6] Таким образом мы рассмотрели представление различных числовых данных в ЭВМ. Автор надеется, что теперь Вы поняли, какая большая разница существует между внутреннем представлением целого числа 2 и вещественного 2.0 . Поэтому удивительным скорее должно быть не то, что для преобразования из REAL в INTEGER используются специальные функции TRUNC( ) и ROUND( ), а то, что такие функции отсутствуют для обратного перевода: учитывая однозначность перевода из INTEGER в REAL Турбо Паскаль "в порядке исключения" выполняет этот перевод автоматически. Символьные и текстовые данные: тип CHAR и его дальнейшее развитие в более поздних версиях ПаскаляВо времена создания Паскаля обработка текстовой информации на ЭВМ делала только самые первые шаги. Поэтому Н.Вирт заложил в первоначальную версию языка единственный тип данных - CHAR, предназначенный для хранения отдельно взятого символа. Текст, являющийся совокупностью символов, может быть получен путем создания массива типа CHAR (о массивах речь впереди). Стремительное увеличение количества задач обработки текстов на ЭВМ привело к созданию новых, более удобных типов данных, например STRING. С точки зрения лаконичности языка эти типы являются избыточными, поскольку любая задача обработки текста по-прежнему может быть реализована в рамках CHAR. Однако с новыми типами данных решение получается гораздо короче и нагляднее. Именно поэтому сейчас уже трудно представить, что когда-то в Паскале не было типа STRING! Рассмотрение принципов хранения текстовых данных в памяти ЭВМ целесообразно начать именно с типа CHAR, значением которого является одиночный символ. Следует иметь ввиду, что к числу символов принадлежат не только буквы (заглавные или строчные, латинские или русские), но и цифры, знаки препинания, спецсимволы типа "=", "(", "&" и т.п. и даже (обратите особое внимание!) пробелы между словами. Да, не удивляйтесь: пустое место в тексте тоже должно иметь свое обозначение. Каждый символ хранится в виде двоичного кода, который является номером символа. Можно сказать, что компьютер имеет собственный алфавит, где весь набор символов строго упорядочен. Количество символов в алфавите тесно связано с двоичным представлением и равняется 28 = 256. Иными словами, каждый символ всегда кодируется 8 битами, т.е. занимает ровно один байт. Как видите, хранится не начертание буквы, а ее номер. Именно по этому номеру воспроизводится вид символа на экране дисплея или на бумаге. Наиболее стабильное положение в алфавитах всех ЭВМ занимают латинские буквы, цифры и некоторые специальные знаки. Это связано с существованием международного стандарта ASCII (American Standard Code for Information Interchange - Американский стандартный код для обмена информацией). Русские же буквы не стандартизированы и могут иметь различную кодировку. Ниже в качестве примера приводится таблица стандартной части алфавита ЭВМ - символы с шестнадцатиричными кодами с 20 до 7F. Пример: код 52 соответствует "R".
Нельзя также пройти мимо еще одного интересного факта: каждый символ текста имеет свой числовой код, но не каждому коду соответствует отображаемый на экране символ. Речь идет о существовании так называемых управляющих кодов, величина которых меньше шестнадцатиричного числа 20 (т.е. 32 в десятичной системе счисления). При получении этих кодов внешние устройства не изображают какого-либо символа, а выполняют те или иные управляющие действия. Так, код 07 вызывает подачу стандартного звукового сигнала, а код 0C - очистку экрана. Особую роль играют коды 0A перевод строки, обозначаемый часто LF) и 0D (возврат каретки - CR). Первый вызывает перемещение в следующую строку без изменения позиции, а второй - на начало текущей строки. Таким образом, для перехода на начало новой строки требуются оба кода и в любом тексте эта "неразлучная пара" кодов хранится после каждой строки. Обратим внимание читателя на то, что названия возврат каретки и перевод строки имеют историческое происхождение и связаны с устройством пишущей машинки. Рассматриваемый тип данных CHAR "по внутреннему устройству" является числом, но в то же время для его преобразования в число используется специальная функция ORD( ). Другая функция - CHR( ) служит для обратного преобразования числа в символ. В настоящее время стандарт ASCII начинает постепенно вытесняться новым международным стандартом - UNICODE. Символ в этом стандарте кодируется уже не одним, а двумя байтами: один из них по-прежнему определяет номер символа в алфавите, а другой хранит номер самого алфавита в стандартном списке алфавитов. Каждый язык, например, русский или греческий, имеет в этом списке свою страничку со вполне определенным номером. Некоторым сложным языкам типа японского выделяется несколько алфавитных страниц. Применение UNICODE позволяет легко включать в текст символы из самых разнообразных языков. Многие современные программные продукты, например, последние версии операционной системы Windows или язык программирования JAVA уже включают в себя поддержку UNICODE. К сожалению, Паскаль пока не содержит типов данных, рассчитанных на UNICODE. Описанный выше тип CHAR предназначен для хранения отдельного символа, что далеко не всегда удобно. Поэтому в более поздних версиях Паскаля появился новый вид данных для хранения текста - STRING (строка). Значением этого типа может служить текстовая строка с максимальной длиной 255 символов. Достоинствами STRING является то, что в одной переменной хранится целая строка, и самое главное, имеется большой набор удобных процедур и функций для обработки находящегося в ней текста. Можно, например, вставить текст в заданное место строки или, наоборот, удалить его, скопировать часть строки в другую переменную, осуществить поиск заданного образца в строке и т.д. Под каждую строковую переменную компилятор Паскаля отводит определенное место в памяти, и это задает ее максимально возможную длину. Например, описание зарезервирует в ОЗУ место под 9 символов. Часто начинающие программисты ничего не указывают после STRING - в этом случае создается строка с максимально возможной длиной 255. Реально не вся отведенная память может быть заполнена, поэтому существует понятие текущей длины строки, которая равна фактическому количеству символов в тексте. Для ее определения имеется специальная функция LENGTH( ). Текущая длина строки всегда храниться в ее нулевом байте; именно поэтому строка более 255 символов принципиально невозможна. В качестве примера на рис.2.1 показана строковая переменная s, созданная по приведенному чуть выше описанию. В ней находится текст из 4 букв 'Text', а байты с пятого по девятый в настоящий момент не используются.
Для тех, кому недостаточно в тексте иметь 255 символов, Borland Pascal предоставляет специальный модуль Strings, который поддерживает работу с так называемыми строками с нуль-окончанием. В них байт длины отсутствует, а конец строки определяется положением специального нуль-символа CHR(0). Принципиальные ограничения на длину такой строки отсутствуют, но 16-битная архитектура MS DOS устанавливает верхний предел в 65535 символов. Отметим, что строки с нуль-окончанием широко используются в Windows, например, для хранения путей дисковых файлов. Логические данные: тип BOOLEANБулевские переменные, названные так в честь известного математика Д.Буля, широко используются в Паскале для хранения результатов тех или иных логических действий. Для этого типа данных возможно всего два значения, которые принято обозначать TRUE и FALSE. Несмотря на то, что для кодирования двух значений хватило бы одного бита, каждая переменная типа BOOLEAN хранится в отдельном байте. В качестве значения FALSE используется 0, а TRUE кодируется 1. Разрешается сравнивать логические значения на больше/меньше: нетрудно догадаться, что FALSE < TRUE. Помимо "классического" логического типа BOOLEAN, в последних версиях Турбо Паскаля существуют типы BYTEBOOL, WORDBOOL и LONGBOOL. INTEGER, CHAR и BOOLEAN как пример порядковых типовЕсли значения какого-либо типа данных являются упорядоченными, т.е. к ним применимы понятия последующий/предыдущий, такой тип называется порядковым (ordinal). Все рассмотренные ранее типы, исключая вещественный и STRING, являются порядковыми. Кроме того, к порядковым типам относятся также перечисление и ограничение. Перечисление является особым типом данных, который описывает сам пользователь путем перечисления всех его допустимых значений. Например: Естественно, что вместо текстовых значений Паскаль везде оперирует их номерами, которые начинаются с нуля (убедитесь, запустив DATA EXPLORER). Указанные в скобках значения используются только в момент трансляции программы и впоследствии не сохраняются. Именно поэтому переменные указанного типа нельзя ввести с клавиатуры или вывести на экран. Ограничение позволяет в любом из порядковых типов выделить диапазон значений, например: Использование ограничения не приводит к изменению внутреннего представления значений переменных: например, для типов t2 и CHAR значение 'A' кодируется одинаково. Все порядковые типы обладают рядом приведенных ниже полезных свойств.
Благодаря упорядоченности, допускается сравнение значений внутри каждого порядкового типа. По ним может организовываться цикл FOR, переменные этого типа могут использоваться в качестве индексов массива. Организация данных в массивыВсе рассмотренные в предыдущем разделе порядковые типы и дополнительно к ним вещественные числа образуют большой и разнообразный класс простых данных. Характерной чертой таких данных является то, что каждая переменная простого типа может единовременно хранить только одно значение. При записи нового значения старое теряется. Кроме того, в Паскале существуют еще и сложные типы данных, которые тем или иным способом объединяют в себе под одним именем совокупность нескольких простых значений. Не запрещается также создавать сложные типы данных от других сложных типов. Одним из первых сложных типов данных в языках программирования был массив (в Паскале он называется ARRAY). Массив состоит из нескольких элементов одинакового типа, объединенных общим именем. Доступ к нужному элементу массива реализуется с помощью индексов. В простейшем случае индекс - это целочисленный номер элемента, но Паскаль разрешает использовать в качестве индекса любой порядковый тип, например, CHAR, перечисление или даже BOOLEAN. Массив может иметь несколько индексов, причем допускается, чтобы они были разного типа. Появление массивов в языках программирования позволило существенно упростить однотипную обработку большого количества данных. Достаточно описать, что делать с одним элементом, а затем просто указать, на какие элементы это действие распространяется. Программы с использованием массивов отличаются простотой, компактностью и наглядностью. В отличие от простых данных, массивам не соответствует какой-либо предопределенный объем ОЗУ - все зависит от типа элементов и их количества. Поэтому большую роль при работе с массивом приобретает его описание. В описании не просто констатируется, что та или иная переменная
является массивом: указываются также типы индексов, по которым легко определить количество элементов массива, и тип его элементов, что позволяет узнать объем памяти под каждый из них. Общий объем памяти вычисляется как произведение этих двух чисел. Например, двумерный массив A, описанный состоит из 260 элементов (латинских букв, как известно, 26) длиной по 2 байта каждый; таким образом, всего под массив требуется отвести 520 байт ОЗУ. Элементы массива хранятся в памяти "вплотную", без всяких разделителей, в чем легко можно убедиться, запустив наш DATA EXPLORER. Для нахождения адреса требуемого элемента достаточно произвести некоторые арифметические вычисления. Рассмотрим этот вопрос подробнее, начав для простоты с одномерного массива. Итак, пусть массив M имеет единственный индекс, который для определенности будем обозначать K. Как мы уже знаем, K обязательно имеет порядковый тип, а значит каждому его значению можно поставить в соответствие целое число. Поэтому, каким бы ни был индекс, его границам соответствуют вполне определенные числа Kmin и Kmax.. Будем также считать, что каждый элемент массива требует B байт памяти (для INTEGER B=2, для BOOLEAN - 1 и т.д.). Тогда адрес произвольного элемента с номером K в массиве будет определяться формулой где A - адрес ОЗУ самого первого элемента с номером Kmin. Преобразуем это выражение к виду Итак, адрес произвольного элемента определяется окончательной формулой A0 - это формальным образом полученная константа, но она имеет простой и понятный смысл: адрес нулевого элемента массива. Подчеркнем, что в массиве вполне может не быть нулевого элемента, но формула все равно остается правильной. Для иллюстрации приведем пример двух массивов К обоим из них применима формула (*), хотя для первого A0 и будет находиться вне массива (см. рис. 2.2).
Аналогичные формулы расчета адреса произвольного элемента могут быть получены и для многомерных массивов. Для наиболее часто встречающегося на практике двумерного массива адрес будет вычисляться по более сложной формуле = A0 + ( j + i * nj ) * B , где количество элементов в строке для краткости обозначено nj = jmax - jmin + 1. Для случая двумерного массива A0 уже не имеет наглядной интерпретации и является формальной константой. При рассмотрении внутреннего представления многомерных массивов следует учитывать правило, что самый правый индекс всегда увеличивается первым [1]. Краткий обзор остальных типов данныхОстается рассмотреть еще несколько типов данных, которые существуют в Турбо Паскале. Ниже будут рассмотрены два сложных типа RECORD (запись) и SET (множество), а также особый тип данных, совершенно не похожий на другие - указатель. Внутреннее представление наиболее сложных типов данных Турбо Паскаля - FILE и OBJECT мы здесь обсуждать не будем. Начнем с записей. Запись, как и массив, образуется из отдельных компонентов, но, в отличие от массива, типы входящих в запись данных могут быть различны. Компоненты записи имеют специальное название - поля. Доступ к полям осуществляется по имени. Записи очень хорошо подходят для создания всевозможных баз данных, так как информация об объектах обычно включает в себя самые разнообразные типы полей: текстовое название, те или иные числовые характеристики, булевские поля, связанные с наличием или отсутствием каких-то свойств и т.д. Даже обычная общепринятая запись даты, состоящая из числа и названия месяца, уже требует типа RECORD! Зная, в каком формате хранятся образующие запись поля, вы без труда разберетесь, как хранятся переменные типа RECORD. Гораздо интереснее кодируется в памяти ЭВМ другой тип - множество. Каждому его элементу соответствует отдельный бит, который установлен в 1, если элемент входит в данное множество, и сброшен в 0, если отсутствует в нем. Таким образом, для хранения множества требуется столько битов, сколько значений могут принимать элементы множества. Для вычисления количества байт под множество в [1] рекомендуется использовать следующую формулу: Число элементов множества не может превышать 256, так что множество никогда не занимает более 32 байт. В качестве примера в таблице 7 приведены различные состояния для переменной P типа множества, описанной следующим образом:
Остается рассмотреть указатели. Указатель - это не само значение, а ссылка на него. Правильнее всего представлять себе указатель в виде адреса ОЗУ, где хранится требуемая информация. Наиболее подготовленные читатели могут самостоятельно модифицировать нашу любимую программу DATA EXPLORER так, чтобы она рассматривала переменную e в ней как адрес памяти, где содержится интересующая Вас информация. Учтите только, что смещение для адреса располагается в младшем слове, а сегментная часть - старшем. Двойное нулевое значение соответствует неопределенному указателю nil [1].
Итак, мы рассмотрели основные принципы представления в памяти ЭВМ всех основных типов данных Паскаля. Автор надеется, что читатели узнали по этому вопросу много интересного, глубже разобрались в Паскале и еще больше его полюбили.
© Е.А.Еремин, 2007 Публикация: Еремин Е.А. Представление информации в ЭВМ средствами Turbo Pascal. "Информатика и образование", 1999, N 3, с.47-58. |