Искусство программирования на Си (984073), страница 17
Текст из файла (страница 17)
Эта процслура мо- того, что производится операция битового "И" массива жст очистить только весь массив целиком. Если в качс- данных с маской. в которой, кроме проверяемого, всс ((ВИа ЕЬтУМ «)паььос(ВМЕ Мелтагяе[И) * аьгпоЦВМЕ ЕЬтууе>)> стас )х) задать число, меньшее, чсм размер массива, всс остальные биты очишсны. Битовый массив при этом нс «дпт и ВМВ ЕЕАЬЬОС[Ьагг И> равно может быть очищено большс, чсм )к> сго началь- измснястся, а полученный рсзультат можст быть ис- [(ВИа ЕЬтХРЕ «>гпаиос[Ьагг, ВМЕ ИаМЯГЕЕ(И> ° аггаоЦВИа ЕЬттуе>) > ных битов. Такая опсрация должна быть корректной, но пользован прог аммой.
«двг(пп вме Реев(ьа > ггпп(ьагг> а прогр ммо . «Вацпп ВИа СЬЕАЕИадт(Ьагг, И> это ужс сложнее (возможно, потрсбустся привлсчснис Результат нс обязательно равен 1, если значснис бита вппапс[Ьагг, Ю, ВАЕВ Иалтятее(В1 * агапоцВМЕ ЕЬттуе>1 некоторой функции) 1; это можст быть любая ненулевая величина. Можно Наконец, рассмотрим опсрации, которые и делают написать макрос так, чтобы возвращалась именно сди- «двт(пп ВАМ ЕЬИОМ[И> ((И> Г ВАЕВ ЕЬВття> битовыс массивы полезными: присвоение биту значс- ница, но это можст снизить эффективность (которая и «Дп(тпе ВАЕВ В1ТИОМ(и) ((И) а В[на ВЬВ1ТЯ) ния 1, сго очистку (т.с.
присвоение биту значения 0) и являстся олной из основных причин использования «Сп((пе ВАЕВ ЯЕТ(Ьагг, И) ((Ьагг)[ВАЕЕ ЕЫОМ(и)) ~ (ВАЕВ ЕЬТТРЕ)1 сс ВИа В1ТИОМ(и)) проверку содержимого. Во-псрвых, опрсдслим нссколь- битовых массивов) бсз особой выгоды. «впцпп вме сьем(ьагг, и> ко вспомогательных макросов: Теперь, наконсц, можно легко написать макрос, ([ьагг)[Влив Вьицм(и>1 а= ([ВАВВ еьтуРЕ)1 сс ВАЕВ В1тивм(и))) «цпт пп ВАВВ ЕЬИОМ(и) ((Н) / ВАВВ ЕЬВтта> инвсртируюший определенный бит в битовом массиве, «Опт[па ВМВ РЬЬР(вагг, И) таким образом. ((ьагг1(вмв еьиаци>1 " [виа еьтуве11 сс виа вттиаци) > Здссь ВАКК ЕЕ)х[(>М опрслсляст индекс элемента «Опт(пп ВАНЕ твят(Ьагг, И) чд«<<).
Игры<битами ибаитаии фЯД Глава 5 ° <й(ЙИ Перасиатреннли< юин С Ш$— ЧастЫ Здесь строка ча!ве 4<= ча1пе-1 представляет собой як<бой возможный перенос при сложении. Пропесс уве- Зеркальное отражение битов что-то вроде ловкого трюка. Поэтому комментарий к личення в 2 раза длины поля при каждом шаге прололней вполне уместен. жастся до тех пор, пока нс будет подсчитано полное Другая простая залача состоит в тол<, как обратить по- хож на гизгоритл< программы ЬВ совп(4, и здесь также В программе Ь<( сопи(4 использован способ вообще число битов 1 в величине ча1ве.
Затем это число возвра- рядок всех битов в величине. Нскоторыс решения этой предполагается, что длина данных составляет 32 бита. без привлечения никла. щастся программой. задачи очень похожи на решения залачн подсчета би- Рассл<отрим, как это происходит, на примере 8-битового И в послелнем примере ЬМ сввп(5 реализован про- тов. В программе Ь<1 геч! использован простой принпип: набора, состоящего из символов: повиднее 1опд Ьас сош<Е4(ппв1дпес 1опд че1пе) ( стой, но часто очень эффективный способ написания величина ча)пе пошагово сдвигается вправо, и на кажче1пе = (ча1пе а Ох55555555) + ((ча1пе» програмл<ы с использованием табл<шы преобразований: дом шаге младший бит тя)пе перемешается в млалший 11 а Ох55555555)7 бит геап(Г, который пошагово сдвигается влево. В про- Сначала, переставив соседние биты, получим: ча1пе = (ча1ее а Ох33333333) + ((нагое » ппи1дпе<Г 1опд Ьлс соппс5(ппи1дпес 1опд ча1пе) грамме предполагается, что значение 5<АЕ1)Е В!ТБ влосввнп ' 2) а Ох33333333)7 ( г определено, как описывалось ранее в этой главе.
ча1пе (ча1ее а Охвгсгвгог] + ((ча1пе » в ае1с сопят ппя1дпес сваг сопле Еав1е(1 = ( Зател<, переставив соседние пары битов, получим. 4) а ОхОЙОФОГОГ)< ппяьдпеи 1опд Ьлг гечз(опв1дпеа< 1опд ча1пе) ча1че (ча1ее а Охвсййвегт) + ((ча1ее » псвдиогв епвг пе<) 1опд гевп11; ча1пе = (ча1ие а ОхООООШГ) + ((ча1ие » 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, зпг 1; пав!две<) 1опд гевп г; Затем, переставив соседние <руины из четырех би- ""16) а ОхООООГГГГ)7 тов, получим в результате набор битов в обратном погеап11 = О; рядке: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 )г пвяздпеб 1опд Ьзс гечЗ(ппяздпеб 1овд ча1пе) ча1пе »= 1; Основная идея этой программы — разлепить вели- ,вгг(г4 ык С Игры с битюги и биитаии Глава 5 %МИ Переносимость программ Листинг 5.2.
Представление объекта как байтового массива. 4!вс1аде <ас01о.в> грие ваха(уозо) Охос,ох8с,ох4с,охсс, с,охсс,ох2с,охас,охбс,охес, Битовыс поля, определенные как 8)йвед !и! или ОХ1с,ох9с,охзс,охдс,охзс,охьс,охте,ох!с, 0 02,0 82,0 42,0 2,0 22,0 2,0 62,0 2 ППЗ!8пед гп(, заведомо либо облалают знаком (могут со- Охзз,охоз,охзз,обоз,охзз,охьз,о 72,охг2, Дсржатъ ОтрипатсяъггЫЕ ВЕЛИЧИНЫ), ггггбп НЕ Обяаааиц Охоа, Охоа, Ох4а,охса, Ох2а, охаа, Охба,охеа, знаком (нс могут солержать отрицательные величины).
ОХ1а,охоа,ох5а,охоа,охза,охьа,охта,ох!а, ПРосто !п( — это в действительности тип со знаком (тот охоб,ох86, Ох46,0хсб,ох26,Охаб,охбб,охеб, жс самый тип, что и а!йвед щт, и ведет себя во всех слуОХ16,0х96,0хзб,охдб,охзб,охьб,охзб,охгб, ° ° ° чаях аналогично). Однако битовое поле эффективно хае,ох8е,ох4е,охсе,ох2е,охае,ехбе,охее, ох1е,ох9е,ох5е,охде,охзе,охье Ох7е,охге ПрсдетаВЛЯЕт ПОДОбпаетЬ тИПа,н В СЛУЧаЕ С ПЕРЕМСННОй Ох01,0х81,Ох41,0хс1,Ох21,Оказ,охб1,0хез, типа )п! компилятор может выбирать, захватит ли по- ох11,0х91,0х51,0хо1,0х31,0хы,ох71,0хг1, добласть только пологкитсльные величины или и полоОХ09,ох89,ох49,0хс9,ох29,0ха9,0хб9,0хе9, жительные, и отрицательные одновременно. При исОх19,0х99,0х59,0хдо,ох39,0ХЬ9,0х79,Ох!9, 0 05,0 85,0 45,0х,о 25,0,0 5,0 5, польщван н битовых полей пред"очтитсльнее О 15,ОХ95,0*55,0х05,0х35,0 Ь5,ОХ75,О !5, Оход,охао,ох40,0хсд,охзд,охад,охбд,охед, сто гпг, тогда Работа Различных компиляторов будет Охзд,ох9д,охзд,охдд,юхзд,ОХЬО,Охтг),Охсд, приволитЬ К ОДНОМУ результату.
охоз,охоз,ох43,охсз,ох23,охаз,охбз,охез, На первыи взгляд битовыс поля кажутся удобным Ох13,0хзз,охзз,охдз,охзз,охьз,охтз,ох!3, инструмснзом манипулирования частями цсльгх всли- ОХ1ь,ох9ь,охзь,охоь,охзь,охьь,охть,ох!в, чин.
К согкалению, в Языке С очень слабо опРсделено, ОХ07,0х87,0х47,0хс7,0х27,ахат,охбт,охез, каким образом компилятор располагает битовые поля. , ОХ)итиатят, Разит, Р,,длы Е,„ЗД ааг~ки К:г г, Л,Гж,г Дигигтиаяк Ы,,КО Ю,авияги Ог„,, г,и, Важи „., лучшим подходом. В настоящее время даже программы, жестко привязаниыс к аппаратной реализации, могут перемещаться на системы других типов. Любой объект в языке С можно рассматривать как последовательность байтов (кроме, быть может, регистровых переменных, которые нс имеют адресов). Можно получить доступ к отдельным байтам, рассматривая объект как лгассив типов впв)йпед сьаг; такие функции, как щешсру, используют это свойство.
Рассмотрим листинг 5.2, где отдельные байты переменной иа!ве выводятся в том порядке, в котором они появляются в памяти, Термин "от младигего к старшему" (!гп1с епгйап) означает, что младший разряд в байте имеет младший адрес, а старший разрял имеет старший адрес. "От старигего к младигему" (Ьгй епгйап) означает, что байты расположены в обратном порядке, т.е. сначала старший разряд, а затем младший. Смешалиый лорядок (пцхсд епд(ап) означает комбинацию этих двух типов. Процессоры 1пге! Х86, гкпользующисся в ПК-совместимых компьютерах, применяют принцип "от младшего к старшему", но другие, такие как Масгпгозь и некоторые рабочие станции, придерживаются варианта "от старшего к младшему".
Из-за этого немедленно возникает проблема при переносе двоичных данных между системами различных типов и даже в ситуации, когда программы компилируются различными компиляторами или при различных установках одного и того жс компилятора. Лвоичные данные, записанные одной программой, моПт быть интерпретированы совершенно иначе при чтс- Игры с бата.ча а баатаяа ~ а Глааа 5 11ерес чатрея я ыа язык С Часть ( Эта структура определяет информацию о некоторого В табл.
5.7 показаны размеры и сдвиги, которые будут 'гпС я19пеб ча1ие7 рода контейнере. Необходимо записать эту информа- испольюваны во внешнем формате. ипягчпеб ииатчиеб ча1ие; цию и файл и затем прочесть сс в другой системе. НаиТаблица 5.7. Размеры полей и сдвиги для /* Перекодарует аепачаау со зааком а даапазоае от -32767 до 32767 а аепачаау без заака от О до более простой и часто наилучший способ, позполяюшнй внешнего представления 52гцс( Соп(а!пег.
сделать это, — записать структуру в текстовом формате, возможно, в одну строку как список с разделитель- Элемент структуры Размер а байтах Сдвиг ипа19пей ча1ие = я19пеб ча1ие >= О 7 я19иеб ча1ие ными запятыми. Рассмотрим простую функцию, кото- 2 0 е абчиеб ча1ие + 65536О; рая получает указатель на структуру и записывает се сараспу 4 2 /я Перекодарует вепачаау без заака а даапазоае от О до 65535 а аепачаау со заакои а даапазоае строкой и текстовом файле; оз)оис 1 б от т -32767 до 32767 Я/ гпг ыг1ге сопга1пег(РЗЬЕ *Яр, сопаг аггисС роз1(юп 2 7 абчпей ча1ие = ипягчпеб ча1ие <ч 32767 Сопга>оег *соигагпег) 7 (1пг)ииа(чиеб ча1ие иге~бы б 9 ( (гпт)(ипагчпей ча1ие-32768)-32767-1; геС и Гргтптт(тр, ьи,а)и,ьб,ай,а.21(и соптахпег->1епОСЬ, Наконец, нам н но оп Оделить по ядок байтов, в Листинг 5.3.