Мобильные персональные компьютеры: виды, варианты исполнения, их сравнение
Автор работы: Пользователь скрыл имя, 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() некорректного значения.