Мобильные персональные компьютеры: виды, варианты исполнения, их сравнение

Автор работы: Пользователь скрыл имя, 27 Февраля 2013 в 13:59, контрольная работа

Описание работы


Ноутбук (англ. notebook – блокнот, блокнотный ПК) – портативный персональный компьютер, в корпусе которого объединены типичные компоненты ПК, включая дисплей, клавиатуру и устройство указания (обычно сенсорная панель, или тачпад), а также аккумуляторные батареи. Ноутбуки отличаются небольшими размерами и весом, время автономной работы ноутбуков изменяется в пределах от 1 до 15 часов.

Содержание работы


1. Настольные ПК: комплектующие, варианты конструктивного исполнения, их сравнение.
2. Типы данных языков программирования, структуры данных.
Практическая часть
Список литературы

Файлы: 1 файл

контрольная по информатике.docx

— 120.75 Кб (Скачать файл)

 

Можно очень коротко охарактеризовать основные возможности, которые обеспечивает механизм записей. Главное - это то, что в одной именованной области  памяти можно хранить совокупность разнотипных именованных полей, причем имена этих полей специфицируются  один раз при определении структурного типа данных.

Понятно, что без записей  можно обойтись, но с их использованием удобнее и экономичнее программировать.

Идея, которую мы обсудим  в этом разделе, тоже в основном относится  к повышению уровня удобств программирования. При реальном программировании достаточно часто возникает желание по-разному интерпретировать содержимое одной и той же области памяти в зависимости от конкретных обстоятельств. Хорошим стилем является использование каждой структурной переменной с некоторым объектом предметной области, к которой относится программа. Поля структуры в этом случае содержат требуемые характеристики объекта. Но любой объект может менять свое состояние и соответственно набор характеристик. Поэтому удобно, продолжая использовать ту же область памяти, иметь возможность понимать ее структуру и содержание таким образом, который согласуется с текущим состоянием объекта.

Понятно, что для того, чтобы получить такую возможность, нужно несколько расширить средства определения структурного типа, введя  вариантность соответствующей структуры. Нужно уметь специфицировать  все возможные варианты структурной  и типовой интерпретации переменных и значений типа записи. Естественно, что любая такая переменная, вне  зависимости от ее конкретной интерпретации, будет занимать один и тот же объем  памяти, определяемый "максимальным" по размеру вариантом.

Наиболее строгое решение  содержится в языках линии Паскаль. В определении всего структурного типа или его завершающей части  можно явно указать специальное  поле перечисляемого типа (дискриминант), значения которого являются метками  соответствующих вариантов типа записи. Для корректного использования  переменных такого типа требуется заносить в поле дискриминанта актуальное значение при изменении интерпретации  переменной и руководствоваться  значением дискриминанта при  доступе к содержимому переменной. Вот пример определения типа записи с вариантами в языке Паскаль:

type person = record lname, fname: alfa;

birthday: date;

marstatus: (single, married);

case sex: (male, female) of male: (weight: real; bearded: boolean);

female: (size: array of integer)

end

(Считается, что типы данных alfa и date уже определены.) После определения переменной типа person в любой момент можно обращаться и к полям weight и bearded, и к элементам массива size, но корректно это следует делать, руководствуясь значением дискриминанта sex.

Более слабый, но эквивалентный  по возможностям механизм поддерживается в языках семейства Си. В этих языках существует специальная разновидность  типов данных, называемая смесью (union). Фактически, смесь - это запись с вариантами, но без явно поддерживаемого дискриминанта. По нашему мнению, решение о применении такого "облегченного" механизма было принято потому, что использование явно задаваемого дискриминанта в языках линии Паскаль все равно является необязательным, а раз так, то при желании можно просто включить дополнительное поле, значение которого будет характеризовать применимый вариант. Приведенный выше пример можно было бы переписать на языке Си следующим образом:

struct person { char lname, fname; integer birthday;

enum { single, married } marstatus;

enum { male, female } sex;

union {struct { float weight; integer bearded } male; integer female;} pers;} 

Множества

Еще одной разновидностью конструируемых типов являются типы множеств. Такие типы поддерживаются только в развитых сильно типизированных языках. В языке Паскаль тип множества определяется конструкцией type T = set of T0, где T0 - встроенный или ранее определенный тип данных (базовый тип). Значениями переменных типа T являются множества элементов типа T0 (в частности, пустые множества).

Для любого типа множества  определены следующие операции: "?" - пересечение множеств, "+" - объединение множеств, "-" - вычитание множеств и "in" - проверка принадлежности к множеству элемента базового типа.

С использованием механизма  множеств можно писать лаконичные и  красивые программы, но нужно отдавать себе отчет в том, что для эффективной  реализации множеств требуются серьезные ограничения их мощности. Обычно в реализациях языков допускаются множества, мощность базового типа которых не превосходит длину машинного слова. Это связано с тем, что перечисленные выше операции допускают эффективную реализацию только в том случае, когда значение множества представляется битовой шкалой, длина которой равна мощности базового типа. "1" означает, что соответствующий элемент базового типа входит в множество, "0" - не входит. Чтобы для выполнения операций над множествами можно было прямо использовать машинные команды, нужно ограничить длину шкалы машинным словом.

 Указатели

 

Понятие указателя в языках программирования является абстракцией  понятия машинного адреса. Подобно  тому, как зная машинный адрес можно  обратиться к нужному элементу памяти, имея значение указателя, можно обратиться к соответствующей переменной. Различие между механизмами указателей в  разных языках состоит главным образом  в том, откуда берется значение указателя. Чем больше возможностей по работе с указателями, тем более эффективную  программу можно написать и тем "опаснее" становится программирование. Обычно возможности оперирования указателями  ограничиваются по мере повышения уровня языка и усиления его типизации.

В любом случае для объявления указательных переменных служат так  называемые указательные, или ссылочные  типы. Для определения указательного  типа, значениями которого являются указатели  на переменные встроенного или ранее  определенного типа T0, в языке  Паскаль используется конструкция  type T = T0. В языке Си отсутствуют отдельные возможности определения указательного типа, и, чтобы объявить переменную var, которая будет содержать указатели на переменные типа T0, используется конструкция T0 *var. Но конечно, это чисто поверхностное отличие, а суть гораздо глубже.

В языках линии Паскаль  переменной указательного типа можно  присваивать только значения, вырабатываемые встроенной процедурой динамического  выделения памяти new, значения переменных того же самого указательного типа и специальное "пустое" ссылочное значение nil, которое входит в любой указательный тип. Не допускаются преобразования типов указателей и какие-либо арифметические действия над их значениями. С переменной-указателем var можно выполнять только операцию var, обеспечивающую доступ к значению переменной типа T0, на которую указывает значение переменной var.

Напротив, в языках Си и  Си++ имеется полная свобода работы с указателями. С помощью операции "&" можно получить значение указателя для любой переменной, над указателями определены арифметические действия, возможно явное преобразование указательных типов и даже преобразование целых типов к указательным типам. В этих языках не фиксируется значение "пустых" (ни на что не ссылающихся) указательных переменных. Имеется лишь рекомендация использовать в качестве такого значения константу с символическим именем NULL, определяемую в библиотечном файле включения. По сути дела, понятие указателя в этих языках очень близко к понятию машинного адреса.

Отмеченные свойства механизма  указателей существенно повлияли на особенности реализации в языках Си и Си++ работы с массивами. Имя массива в этих языках интерпретируется как имя константного указателя на первый элемент массива. Операция доступа к i-тому элементу массива arr хотя и обозначается как и в языках линии Паскаль arr[i], имеет низкоуровневую интерпретацию *(arr+i). Поэтому было логично допустить подобную запись для любой переменной var с указательным типом: var[i] интерпретируется как *(var+i). По этой причине понятие массива в Си/Си++ существенно отличается от соответствующего понятия в Паскале. Размер массива существенен только при его определении и используется для выделения соответствующего объема памяти. При работе программы используется только имя массива как константный указатель соответствующего типа. Нет операций над "массивными переменными" целиком; в частности, невозможно присваивание. Фактически отсутствует поддержка массивов как параметров вызова функций - передаются именно значения указателей (в связи с этим, при описании формального параметра-массива его размер не указывается). Функции не могут вырабатывать "массивные" значения.

Как отмечалось выше, особенности  работы с указателями в некоторой  степени повлияли и на организацию  структур. Хотя в описаниях языков Си и Си++ и рекомендациях по программированию присутствует настоятельный совет обращаться к полям структурных переменныхтолько по их именам, известно, что каждое имя на самом деле интерпретируется как смещение от начала структуры. Поэтому, имея значение указателя на начало структурной переменной и манипулируя известными длинами полей структуры, технически можно добраться до любого поля, не используя его имя.

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

Динамическое распределение  памяти и списки

При решении ряда задач  становится неудобно, неэффективно, а  иногда и просто невозможно обойтись использованием памяти, выделяемой компилятором и системой поддержки времени  выполнения в соответствии с явными описаниями переменных в программе. Во всех языках, более или менее  приспособленных к практическому  применению, имеется возможность  явно запрашивать и использовать области так называемой динамической памяти. Такие области принято называть "динамическими переменными". Возможности создания и использования динамических переменных тесно связаны с механизмами указателей, поскольку динамическая переменная не имеет статически заданного имени, и доступ к такой переменной возможен только через указатель.

Как и во многих обсуждавшихся  ранее случаях, механизмы работы с динамической памятью в языках с сильной типизацией существенно  отличаются от соответствующих механизмов языков со слабой типизацией. В языках линии Паскаль для запроса  динамических переменных используется встроенная процедура new(var), где var - переменная некоторого ссылочного типа T. Если тип T определялся конструкцией type T = T0, то при выполнении этой процедуры подсистема поддержки времени выполнения выделяет динамическую область памяти с размером, достаточным для размещения переменных типа T0, и переменной var присваивается ссылочное значение, обеспечивающее доступ к выделенной динамической переменной.

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

Первый - это явное использование  встроенной процедуры dispose(var), где var - переменная ссылочного типа, значение которой указывает на ранее выделенную и еще не освобожденную динамическую переменную. Строго говоря, при выполнении процедуры dispose должно быть не только произведено действие по освобождению памяти, но также переменной var и всем переменным того же ссылочного типа с тем же значением должно быть присвоено значение nil. Это гарантировало бы, что после вызова dispose в программе были бы невозможны некорректные обращения к освобожденной области памяти. К сожалению, обычно из соображений эффективности такая глобальная очистка не производится, и программирование с использованием динамической памяти становится достаточно опасным.

Второй механизм, обеспечивающий более безопасное программирование, состоит в том, что подсистема поддержки времени выполнения хранит ссылки на все выделенные динамические переменные и время от времени (обычно, когда объем свободной динамической памяти достигает некоторого нижнего  предела) автоматически запускает  процедуру "сборки мусора". Процедура  просматривает содержимое всех существующих к этому моменту ссылочных  переменных, и если оказывается что некоторые ссылки не являются значением ни одной ссылочной переменной, освобождает соответствующие области динамической памяти. Заметим, что это является возможным в силу наличия строгой типизации ссылочных переменных и отсутствия явных или неявных преобразований их типов.

Работа с динамической памятью в языках Си/Си++ гораздо проще и опаснее. Правильнее сказать, что в самих языках средства динамического выделения и освобождения памяти вообще отсутствуют. При программировании на языке Си для этих целей используются несколько функций из стандартной библиотеки stdlib, специфицированной в стандарте ANSI C. При реализации языка Си в среде ОС UNIX используются соответствующие функции из системной библиотеки stdlib.

Базовой функцией для выделения  памяти является malloc(), входным параметром которой является размер требуемой области динамической памяти в байтах, а выходным - значение типа *void, указывающее на первый байт выделенной области. Гарантируется, что размер выделенной области будет не меньше запрашиваемого и что область будет выравнена так, чтобы в ней можно было корректно разместить значение любого типа данных. Тем самым, чтобы использовать значение, возвращаемое функцией malloc(), необходимо явно преобразовать его тип к нужному указательному типу.

Для освобождения ранее выделенной области динамической памяти используется функция free(). Ее входным параметром является значение типа *void, которое должно указывать на начало ранее выделенной динамической области. Поведение программы непредсказуемо при использовании указателей на ранее освобожденную память и при задании в качестве параметра функции free() некорректного значения.

Информация о работе Мобильные персональные компьютеры: виды, варианты исполнения, их сравнение