ИД "Мой компьютер"   "Игроград"   "Реальность фантастики"   Ассамблея "Портал"
Сделать стартовой   

 
Домашняя страница
Расширенный поиск
E-mail

 

N 16 (447)




МОЙ КОМПЬЮТЕР




  Новости:

 
МК
Украина
Игры
Интернет
Железо
Софт
Пресс-релизы

  Статьи:

 
Уголок читателя
Прочее
Имеющий уши
Программирование
Интернет
Железо
Софт
Игры


 
КОНКУРСЫ



Правила конкурсов

Конкурс "АВЧ"

Рейтинг победителей


ОПРОС

Вы посещаете нас:
первый раз
1-2 раза в месяц
1-2 раза в неделю
1-2 раза в день
более 2-х раз в день Что привело Вас к нам?
поиск информации
интерес к статьям
интерес к новостям
любопытство
реклама
другое








боулинг

ads.mycomputer.ua

ads.mycomputer.ua

ads.mycomputer.ua

ads.mycomputer.ua

ads.mycomputer.ua













Argumentum ad ignorantiam!

 

статьи
Программирование



 

Прочее  
Visual basic  
Delphi  
C++  
Интернет приложения  
Теория  




    Delphi


Адрес, прописка…

Ярик Уланович aka Mahpella
N 4 (435) 20.01.2007


Сегодня мы займемся адресной арифметикой в Делфи. Перестаньте так на меня смотреть — я прекрасно знаю, что в Делфи нет адресной арифметики. В смысле, такой как в Си («сишники» посмеиваются). Можно присваивать один указатель другому, сравнивать их на равно/не равно — и все. Нет сложения, вычитания указателей и прочих полезных вещей. Но, как говорил один мой преподаватель, если очень хочется, то можно. А я очень люблю эту среду разработки, так что всеми силами пытаюсь показать, что в ней можно все. В крайнем случае, если Делфи чего-то и не может, то она имеет BASM (Built-in-Assembler), а уж он точно круче всех. Так что возьмем пока его на вооружение.

О файлах и памяти

Многие не знают (я и сам не знал, пока мне не рассказали) об одной возможности при написании программ. Она очевидна, но пока не возникает потребность, никто об этом не задумывается. Я имею ввиду работу в файле «без типа». Суть в том, что наши объемные данные мы записываем в этот самый файл на винте, а не в оперативку. Если надо изменить какую-то часть, то читаем в память, изменяем и записываем обратно. Мы создаем как бы свою личную маленькую оперативную память. PhotoShop, например, так поступает. Но эту технологию оправданно применять лишь в том случае, если вам мало всей оперативной памяти, ведь винчестер работает во много раз медленнее оперативной памяти. Да и программировать становится труднее, ведь в случае с оперативкой мы не заботимся о выделении/освобождении динамической памяти — GetMem, FreeMem и все. В случае же файла нам придется писать эти процедуры самим, создавать список дыр (свободных участков внутри файла), процедуры обслуживания этого списка. Создавать, в общем, механизмы управления памятью, которые уже реализованы в ОС.

Я писал однажды программу, работающую в файле. Труднее, конечно, чем в памяти, но написал. Что мне понравилось, так это возможность бродить по всему файлу. Можно спозиционироваться на любой байтик. Потом я вернулся в динамическую память. И для решения проблем, которые в файле решались легко (переместить указатель на четыре байта), в памяти пришлось применять другие способы. То есть мне не хватало возможностей адресной арифметики.

Поясню на примере.

Чтобы записать в файл значение какой-то переменной, нам кроме этой переменной ничего больше не нужно, ведь ее размер можно узнать с помощью функции SizeOf. Например, если a: integer, f: file, то BlockWrite(f, a, SizeOf(a)). Чтобы записать некоторый объект в памяти, нужно иметь указатель на этот объект и его размер:

Переменную a тоже можно записать с помощью указателя на нее:

Мне надо было написать универсальную процедуру записи в файл объектов (под словом объект я имею ввиду не тот объект, который основа ООП, а просто некоторую запись, например, как объявленную ниже):

Конечно, можно написать процедуру, в которую надо передавать адрес, ключевое слово (необходимо для сортировки) и размер. Но ведь эти данные хранятся в самой записи (первые и вторые четыре байта), так что мы будем передавать лишнее. Одним словом, процедуре надо передавать только адрес. Ключевое поле и размер она должна сама суметь прочитать. С ключевым полем все понятно, адрес на объект указывает прямо на него, поэтому легко можно прочитать так: prockey := integer(p). С полем размера тоже было бы аналогично, если бы нам сдвинуть указатель вверх на четыре байта (говоря «вверх», я имею ввиду «в сторону возрастания адресов»). Так что налицо необходимость адресной арифметики. Но Делфи рулит, поэтому можно обойтись без нее!

Адресная арифметика без изменения адресов

Сейчас я покажу, как можно прочитать вторые четыре байта, если указатель указывает на первые. Объявим еще такое:

Повесьте где-то на ButtonClick, чтобы проверить работоспособность.

Делфи рулит! Развить эту идею не составляет труда: используем массив не integer, а byte, получаем доступ к отдельным байтам, и так дальше. Как видите, без адресной арифметики вполне можно обойтись, но все же утрем сишникам нос и покажем, что в Делфи можно проводить те же операции с адресами.

Вариант 1. Асм

Пусть у нас есть переменная-указатель

Маленький пример кода, с помощью которого можно делать с этим указателем что угодно:

Все просто! Теперь вместо add подставляете то, что нужно вам — и юзаете на здоровье! Приведу еще пример сложения двух указателей p1 и p2 в третий p:

Ассемблер рулит! Вот только сишники будут говорить, что ассемблер и Делфи — разные вещи, так что реализованная выше адресная арифметика — заслуга совсем не Делфи. Что ж, оставим асм в покое и реализуем первый пример чисто на Делфи.

Вариант 2. Без асма

Для этого нам потребуется еще пара переменных — a: LongInt (4 байта, целое, беззнаковое) и указатель на переменные типа LongInt: pInt: ^LongInt.

Вышло даже на целую строчку короче!

Так что если вы собрались переходить на Си из-за того, что не нашли в Делфи аналогичных возможностей работы с адресами, то не спешите, а лучше пошевелите мозгами, ибо Delphi — the best!







Расширенный поиск 
 

О проекте  Рекламодателям  Карта сайта  Контакт  Обратная связь 

© ИД "Мой компьютер"®, 1998-2004