Здавалка
Главная | Обратная связь

Комментарии к коду.



Операция 1. x = 03; y = 02; z = 01; k = x|y&z;Вследствие приоритетов операций: k = (x|(y&z));. Самое внутреннее выражение вычисляется первым. k = (x|(02&01)); 02 & 01 = 00000010 & 00000001 = 00000000 = 0 k = (x|00); 03 | 00 = 00000011 | 00000000 = 00000011 = 03 03
Операция 2. x = 03; y = 02; z = 01; k = x|y&~z; k = (x|(y&(~z))); ~00000001 = 11111110 02 & 11111110 = 000000010 & 11111110 = 000000010 = 02 03 | 02 = 00000011 | 000000010 = 00000011 = 03 3
Операция 3. x = 03; y = 02; z = 01; k = x^y&~z; k = (03^02); 1
Операция 4. x = 03; y = 02; z = 01; k = x&y&&z; k = ((x&y)&&z); k = ((03&02)&&z); k = (02&&z); k = (true&&z); k = (1&&01); k = (true&&true) true или 1
Операция 5. x = 01; k = !x|x; k = ((!x)|x); k = ((!true)|x); k = (false|01); k = (0|01); 1
Операция 6. x = 01; k = -x|x; k = ((-x)|x); k = (-01|01); -01 | 01 = 11111111 | 00000001 = 11111111 = -1 -1
Операция 7. x = 01; k = x^x; k = (01^01); 0
Операция 8. x = 01; x <<= 3; x = 01<<3; 01 << 3 = 000000001 << 3 = 00001000 = 8 x = 8; 8
Операция 9. y = -01; y <<= 3; y = -01<<3 -01 << 3 = 11111111 << 3 = 11111000 = -8 y = -8; -8
Операция 10. y = -08; y >>= 3; y = -08>>3; -1

Примечание:В некоторых случаях вместо -1 может получиться другой результат (8191). Появление этого значения объясняется тем, что на некоторых компьютерах при операции сдвига знак числа может не сохраниться. Не все трансляторы языка C гарантируют, что операция сдвига арифметически корректна, поэтому в любом случае более ясным способом деления на 8 было бы явное деление y=y/8.

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           

Объединения.

Объединения в языке C подобны структурам, однако в каждый момент времени может использоваться (является активным) только один из его компонентов. Шаблон объединения может задаваться записью вида:

union { <имя типа1> <компонента1>; <имя типа2> <компонента2>; . . . <имя типаN> <компонентаN>; };

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

Доступ к компонентам объединения осуществляется тем же способом, что и к компонентам структур.

Пример.

#include <iostream>using namespace std; union Test{ int a; char b; }kkk; void main (){ kkk.a = 65; cout<<kkk.a<<" "; // число 65 cout<<kkk.b;// символ А (соответствующий этому числу)}

В качестве более осмысленного примера объекта типа union рассмотрим объединение geom_fig[1]:

union { int radius; // Окружность. int a[2]; // Прямоугольник. int b[3]; // Треугольник. } geom_fig;

В этом примере обрабатывается только активный компонент, то есть компонент, который последним получает свое значение. Например, после присваивания значения компоненту radius не имеет смысла обращение к массиву b.

Примечание:Обратите внимание на то, что на одних компьютерах поля битов размещаются слева направо, на других - справа налево. Это значит, что при всей полезности работы с ними, если формат данных, с которыми мы имеем дело, дан нам свыше, то необходимо самым тщательным образом исследовать порядок расположения полей; программы, зависящие от такого рода вещей, не переносимы.

Выводы

Объединения применяются для:

  • минимизации используемого объема памяти, если в каждый момент времени только один объект из многих является активным;
  • интерпретации основного представления объекта одного типа, как если бы этому объекту был присвоен другой тип.

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

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           

Битовые поля.

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

Описание поля битов состоит из описания типа поля, его имени и указанного после двоеточия размера поля в битах, например: unsigned status: 6;.

Если имя поля опущено, то создается скрытое поле. Если размер поля битов представлен числом 0, то следующее поле битов начнется с границы машинного слова*.

Пример.

#include <iostream>using namespace std;void Binary(unsigned);void main(){ struct Bits { unsigned bit1: 3; unsigned bit2: 2; unsigned bit3: 3; } Good; Good.bit1 = 4; Good.bit2 = 3; Good.bit3 = 6; cout<<"Show: "<<Good.bit1<<" "; cout<<Good.bit2<<" "; cout<<Good.bit3<<"\n\n"; cout << "Sum: "; Binary(Good.bit1 + Good.bit2 + Good.bit3);} // Функция выводит на экран двоичное представление числа A.void Binary (unsigned A) { int i,N; if(A>255) N = 15; else N = 7; for (i=N; i >= 0; i--) { cout<<((A>>i)&1); if(i==8) cout<<" "; } cout<<"\n\n";}

* Примечание: Машинное слово. - набор из 2-х 4-х или 8-ми последовательных байтов, обрабатываемый аппаратной частью системы как единое целое.

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           

Домашнее задание

1. Написать программу для хранения в битовом поле информации о конфигурации компьютера. Например: Корпус AT – 0, ATX – 1; Видео на борту – 0, карта – 1 и так далее.

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

3. Создать битовое поле для хранения времени (часы, минуты, секунды, миллисекунды). Написать функции для установки и получения времени в(из) битовое(-го) поле(-я).

Предыдущая Оглавление Следующая

 


 

Предыдущая Оглавление Следующая

Урок №18.

  • Препроцессор.
  • Определение констант с помощью #define.
  • Условная компиляция.
  • Другие директивы препроцессора.
  • Разнесение проекта по несколько файлов.
  • Экзаменационные задания.
Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           

Препроцессор.

Препроцессор - это программа, которая производит некоторые (иногда весьма значительные) манипуляции с первоначальным текстом программы перед тем, как он подвергается компиляции. Будучи дословно переведенным, с английского, слово препроцессор означает предварительный обрабатыватель

Препроцессоры создают входной текст для компиляторов и могут выполнять следующие функции:

  • обработку макроопределений;
  • включение файлов;
  • "рациональную" предобработку;
  • расширение языка.

Например, весьма часто в программах приходится использовать "ничего не говорящие" числа. Это могут быть какие-то математические константы или размеры используемых в программе массивов и т.д. Общепризнано, что обилие таких констант затрудняет понимание программ и считается признаком плохого стиля программирования. В среде программистов такие константы получили язвительное название магических чисел. Чтобы программа не изобиловала ими, языки программирования позволяют дать константе имя и далее использовать его везде вместо самой константы.

В языке C такую возможность обеспечивает препроцессор. Например, с помощью определений

#define P1 3.14159#define E 2.71284

препроцессор заменит в программе все имена P1 и E на соответствующие числовые константы. Теперь, когда вы обнаружите, что неправильно написали приближенное значение основания натуральных логарифмов, вам достаточно исправить единственную строку с определением константы, а не просматривать всю программу:

#define E 2.71828

Препроцессор языка C позволяет переопределять не только константы, но и целиком программные конструкции. Например, можно написать определение:

#define forever for(;;)

и затем всюду писать бесконечные циклы в виде:

forever { <тело цикла> }

А если вам не нравятся фигурные скобки, то определите

#define begin {#define end }

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

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

#include <iostream>

Когда исходный текст программы обрабатывается препроцессором, на место этой инструкции ставится содержимое файла iostream, содержащего макроопределения и объявления данных, необходимых для работы потоков ввода-вывода.

Оператор (директива) препроцессора - это одна строка исходного текста, начинающаяся с символа #, за которым следуют название оператора (define, pragma, include, if) и операнды. Операторы препроцессора могут появляться в любом месте программы, и их действие распространяется на весь исходный файл.

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           






©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.