Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Visual_Studio_2010

.pdf
Скачиваний:
109
Добавлен:
03.03.2016
Размер:
5.94 Mб
Скачать

В созданном шаблоне-структуре с дескриптором packed_struct первый член не имеет имени. Символ :3 задает три безымянных бита. Второй, третий и четвертый члены структуры – f1, f2, f3 также имеют тип unsigned int. Символ :1 говорит о том, что в данном члене структуры будет храниться 1 бит. Член структуры с именем type в памяти занимает 8 бит, член структуры index рассчитан на хранение 18 бит.

Для заданного шаблона структуры можно определить структурную переменную, например

struct packed_struct packed_data;

После этого можно присваивать значения полям структуры: packed_data.type = 7;

Если ранее была объявлена какая-то переменная, например n, то присвоение может быть таким:

packed_data.type = n;

При этом нет необходимости беспокоиться о том, что значение переменной n будет слишком большим. Только младшие 8 бит будут учитываться при присваивании значения для поля packed_data.type. Для извлечения битовых полей структуры можно использовать обычное утверждение:

n = packed_data.type;

После извлечения значения поля type будет произведен сдвиг в сторону младших бит.

Битовые поля могут быть объявлены только как тип int (в стандарте С99 также _Bool), от реализации которого зависит, будет он знаковым (signed) или беззнаковым (unsigned). Для исключения неоднозначности следует использовать явные объявления: signed int или unsigned int. Битовые поля нельзя объединять в массивы, нельзя использовать адрес битового поля, поэтому не может быть такого типа, как указатель на битовое поле [2]. Компилятор языка программирования С не переупорядочивает битовые поля для получения оптимального распределения памяти. Но в некоторых случаях может производиться выравнивание за счет безымянного поля. Это может использоваться для выравнивания следующего поля структуры по границе блока [2].

С помощью битовых полей можно формировать объекты с длиной внутреннего представления, не кратной байту.

ПРАКТИЧЕСКАЯ ЧАСТЬ

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

Для решения примера зададим число, которое представим в виде нескольких разрядов, после чего через операции побитового сдвига изменим его и выведем на консоль.

271

Программный код решения примера

#include <stdio.h> #include <conio.h>

// Прототип функции

void printBits(unsigned int var);

// Главная функция int main (void) {

unsigned int number;

printf("\n The program on demonstration digit-by-digit operation of denying ( ~ )\n");

printf("\n\t Enter a whole number of unsigned: "); scanf_s("%u", &number);

printf("\n\t Binary representation of the starting number and\n");

printf("\t Binary representation of bitwise negation of the initial number:\n");

printBits(number); //Исходное число printBits(~number); // Число после поразрядного дополнения

printf("\n\n Press any key: "); _getch();

return 0;

}

// Функция побитового представления целого числа без знака void printBits(unsigned int var)

{

unsigned int b;

unsigned int mask = 1 << 31; // shift to 31 bit printf("\n\t %10u = ", var);

for (b = 1; b <= 32; ++b) {

printf("%c", var & mask ? '1' : '0'); var <<= 1; // or: var = var << 1;

if (b % 8 == 0) putchar(' ');

}

}

В программе применен форматный ввод числа в виде %u и вывод числа в виде %10u, где u используется для беззнакового типа числа, 10 – количество позиций, отводимое для десятичного числа. Предполагается, что заданное число может быть представлено 32 разрядами: по 4 группы с 8 разрядами (4 байта по 8 бит в каждом). Применение оператора сдвига (<<) позволяет все биты числа сдвигать на единицу (действие в цикле for) влево. При этом используется операция поразрядного И. С помощью оператора условия (?) осуществляется замена 1 на 0 и наоборот.

272

Возможный результат выполнения программы показан на рис.16.1. Видно, что все нули или единицы исходного числа (в двоичном представлении) были инвертированы.

Рис. 16.1. Поразрядное инвертирование целого числа

Задание1

1.Проверьте результат выполнения программы с помощью инженерного калькулятора calc операционной системы Windows.

2.Выполните раздельное объявление и раздельное определение (инициализацию с поразрядным сдвигом) переменной mask.

3.В теле цикла for вместо функции printf() примените putchar().

4.Дополните программу выводом результатов в файл compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа.

5.В качестве стартового числа примите год рождения пользователя.

Пример 2. Написать программу выполнения поразрядной операции И над двумя целыми числами, представленными в двоичной системе счисления для 32разрядного компьютера.

Одно из чисел будем считать маской, относительно которой «просеваются» единицы двоичного числа.

Программный код решения примера

#include <stdio.h>

#include <conio.h>

// Прототип функции

void printBits(unsigned int var);

// Главная функция int main (void)

{

unsigned int number, mask;

printf("\n The program on demonstration digit-by-digit operation And ( & )\n");

printf("\n\t Enter a whole number of unsigned: "); scanf_s("%u", &number);

273

printf("\t Enter the number of unsigned-mask: "); scanf_s("%u", &mask);

printf("\n\t Binary representation of the starting number and (%u) and\n", number);

printf("\t Binary representation of the number-masks (%u):\n", mask);

printBits(number);

printBits(mask);

// Число после поразрядного умножения (И) printBits(number & mask);

printf("\n\n Press any key: "); _getch();

return 0;

}

// Функция побитового представления целого числа без знака void printBits(unsigned int var) {

unsigned int b;

unsigned int mask = 1 << 31; // shift to 31 bit printf("\n\t %10u = ", var);

for (b = 1; b <= 32; ++b) { printf("%c", var & mask ? '1' : '0'); var <<= 1; // or: var = var << 1;

if (b % 8 == 0) putchar(' ');

}

}

В программе операция поразрядного умножения И закладывается в фактический параметр функции printBits().

Возможный результат выполнения программы представлен на рис.16.2.

Рис. 16.2. Результат поразрядного оператора И над двумя числами

274

Как видно из рис. 16.2, битовая единица первого числа «проходит» в результат, если в маске на этом же месте (в том же разряде) также находится битовая единица. В результате получается новое число – 32.

Задание2

1.В качестве стартового числа примите год рождения пользователя, а в качестве маски – число рождения.

2.Примените операцию поразрядного умножения к введенным отрицательным числам и выведите результат на консоль. Сравните с тем, что выво-

дит функция printBits().

3.Вместо оператора условия ? примените другой способ вывода 1 или 0 после выполнения поразрядной операции И.

4.Консольный вывод запишите в текстовый файл с именем compX.txt, где Х – номер компьютера, на котором выполняется лабораторная работа.

Пример 3. Написать программу демонстрации поразрядной операции ИЛИ. Программный код решения примера

#include <stdio.h>

#include <conio.h>

// Прототип функции

void printBits(unsigned int var);

// Главная функция int main (void)

{

unsigned int number1, number2;

printf("\n The program on demonstration digit-by-digit operator OR ( | ):\n");

printf("\n\t Enter the unsigned number of N1: "); scanf_s("%u", &number1);

printf("\t Enter the unsigned number of N2: "); scanf_s("%u", &number2);

printf("\n\t Binary representation of the number of N1 (%u) and\n", number1);

printf("\t Binary representation of the number of N2

(%u):\n", number2); printBits(number1); printBits(number2);

// Число после поразрядного сложения (ИЛИ) printBits(number1 | number2);

printf("\n\n Press any key: "); _getch();

return 0;

}

275

// Функция побитового представления целого числа без знака void printBits(unsigned int var)

{

unsigned int b;

unsigned int num = 1 << 31;

printf("\n\t %10u = ", var);

for (b = 1; b <= 32; ++b)

{

printf("%c", var & num ? '1' : '0'); var <<= 1; // or: var = var << 1;

if (b % 8 == 0) putchar(' ');

}

}

В программе, как и в предыдущем примере, использована функция printBits(). Она при необходимости преобразует десятичные числа в двоичные. Входным параметром функции является поразрядное включающее ИЛИ над двумя операндами в главной функции main().

Возможный результат выполнения программы показан на рис.16.3.

Рис.16.3. Результат поразрядного включающего оператора ИЛИ

Как видно из полученного результата, поразрядная операция ИЛИ представляет собой побитовое сложение чисел при условии, что 1 + 1 = 1.

Задание3

1.В качестве исходных чисел примите год и число рождения пользователя.

2.Произведите операцию включающего ИЛИ над двумя десятичными числами в соответствии с предыдущим пунктом задания. Операцию выполните в главной функции main().

3.Видоизмените программу для случая, когда имеется 16-разрядный компьютер.

Пример 4. Написать программу демонстрации поразрядного исключающе-

го ИЛИ.

276

Программный код решения примера

#include <stdio.h> #include <conio.h>

// Прототип функции

void printBits(unsigned int var);

int main (void)

{

unsigned int number1, number2;

printf("\n The program on demonstration digit-by-digit excluding operator OR ( ^ ):\n");

printf("\n\t Enter the unsigned number of N1: "); scanf_s("%u", &number1);

printf("\t Enter the unsigned number of N2: "); scanf_s("%u", &number2);

printf("\n\t Binary representation of the number of N1 (%u) and\n", number1);

printf("\t Binary representation of the number of N2 (%u):\n", number2);

printBits(number1);

printBits(number2);

printBits(number1 ^ number2); // Число после операции ^

printf("\n\n Press any key: ");

_getch(); return 0;

}

// Функция побитового представления целого числа без знака void printBits(unsigned int var)

{

unsigned int b;

unsigned int num = 1 << 31;

printf("\n\t %10u = ", var);

for (b = 1; b <= 32; ++b)

{

printf("%c", var & num ? '1' : '0'); var <<= 1; // or: var = var << 1;

if (b % 8 == 0) putchar(' ');

}

}

277

Возможный результат выполнения программы приведен на рис.16.4.

Рис. 16.4. Результат поразрядного исключающего оператора ИЛИ

Задание4

1.В качестве исходных десятичных чисел примите год и число рождения пользователя.

2.Произведите операцию исключающего ИЛИ над двумя десятичными числами в соответствии с предыдущим пунктом задания. Операцию выполните в главной функции main().

3.Подсчитайте число итераций оператора цикла for.

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

Программный код решения примера

#include <stdio.h>

#include <conio.h>

const char basestr[16] =

{'0','1','2','3','4','5','6','7','8','9',

'A','B','C','D','E','F'};

const char *two16[16] = {"0000","0001","0010","0011","0100","0101","0110","0111",

"1000","1001", // 0,1,2,3,4,5,6,7,8,9

"1010","1011","1100","1101","1110","1111"}; //A,B,C,D,E,F

// Прототипы функций

char *dec2hex(unsigned int var);

void printHex2Bin(unsigned int number);

// Главная функция int main (void)

{

int d12;

unsigned int number1, number2; char ch, *NUM1;

278

printf("\n The program on demonstration digit-by-digit operations\n with hexadecimal numbers\n");

printf("\n\t Enter the unsigned number of N1: "); scanf_s("%u", &number1);

printf("\t Enter the unsigned number of N2: "); scanf_s("%u", &number2);

_flushall();

//Для контроля перевода десятичного числа в шестнадцатеричное printf("\n\t Hexadecimal numbers: %X, %X\n", number1,number2);

printf("\n\t Enter bit operation ( &, |, ^, ~ ): "); scanf_s("%c", &ch);

switch (ch) { case '&':

NUM1 = dec2hex(number1 & number2); printHex2Bin(number1 & number2); break;

case '|':

NUM1 = dec2hex(number1 | number2); printHex2Bin(number1 | number2); break;

case '^':

NUM1 = dec2hex(number1 ^ number2); printHex2Bin(number1 ^ number2); break;

case '~':

printf("\t Type 1 - for the first number; type 2 - for the second number: ");

scanf_s("%d", &d12); _flushall();

if (d12 == 1) {

NUM1 = dec2hex(~number1); printHex2Bin(~number1); }

else {

NUM1 = dec2hex(~number2); printHex2Bin(~number2); }

break;

default :

fprintf(stdout, "\n\t Unknown symbol."); break;

}

printf("\n\n Press any key: "); _getch();

return 0;

}

279

char *dec2hex(unsigned int var) { int i, j, number[64], k = 0; unsigned int base = 16;

char Hex[128], *PTR = Hex;

do {

number[k] = var % base; ++ k;

var /= base;

} while (var != 0);

for (i = k-1, j = 0; i >= 0; --i, ++j) { Hex[j] = (char )basestr[number[i]]; PTR[j] = Hex[j];

}

PTR[j] = '\0'; return (PTR);

}

void printHex2Bin(unsigned int number) { unsigned int i, num = 1 << 31;

printf("\n Hexadecimal number: %s\n", dec2hex(number)); printf(" Binary equivalent:\n ");

for (i = 1; i <= 32; ++i) {

printf("%2c", (number & num )? '1' : '0'); number <<= 1;

if (i % 8 == 0) printf(" ");

}

}

В программе используется функция

char *dec2hex(unsigned int var);

Это дает возможность возвращать указатель с адресом необходимого символьного массива. Обратите внимание на выполнение операции завершения строки в функции *dec2hex() для указателя *PTR.

Возможный результат выполнения программы представлен на рис.16.5.

Рис. 16.5. Пример побитовых операций с шестнадцатеричными числами

280

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]