А. Григорьев - О чём не пишут в книгах по Delphi

Тут можно читать онлайн А. Григорьев - О чём не пишут в книгах по Delphi - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство БХВ-Петербург, год 2008. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    О чём не пишут в книгах по Delphi
  • Автор:
  • Жанр:
  • Издательство:
    БХВ-Петербург
  • Год:
    2008
  • Город:
    СПб
  • ISBN:
    978-5-9775-019003
  • Рейтинг:
    4.25/5. Голосов: 81
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

А. Григорьев - О чём не пишут в книгах по Delphi краткое содержание

О чём не пишут в книгах по Delphi - описание и краткое содержание, автор А. Григорьев, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.

Для программистов

О чём не пишут в книгах по Delphi - читать онлайн бесплатно ознакомительный отрывок

О чём не пишут в книгах по Delphi - читать книгу онлайн бесплатно (ознакомительный отрывок), автор А. Григорьев
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Листинг 3.20. Сравнение строк типа PChar, заданных одинаковыми литералами

procedure TForm1.Button2Click(Sender: TObject);

var

P1, P2: PChar;

begin

P1 := 'Test';

P2 := 'Test';

if P1 = P2 then Label1.Caption := 'Равно'

else Label1.Caption := 'Не равно';

end;

Разница только в том, что строки хранятся не в динамической памяти, a в сегменте кода. Тем не менее на экране появится надпись Равно. Это происходит, разумеется, не потому, что сравнивается содержимое строк, а потому, что в данном случае два указателя оказываются равными. Компилятор поступает достаточно интеллектуально: видя, что в разных местах указаны литералы с одинаковым значением, он выделяет для такого литерала место только один раз, а потом помещает в разные указатели один адрес. Поэтому сравнение дает правильный (с интуитивной точки зрения) результат.

Такое положение дел только запутывает ситуацию со сравнением PChar: написав подобный тест, человек может сделать вывод, что строки PCharсравниваются не по указателю, а по значению, и действовать под руководством этого заблуждения.

Раз уж мы столкнулись с такой особенностью компилятора, немного отвлечемся от сравнения строк и "копнем" этот вопрос немного глубже. В частности, выясним, распространяется ли "интеллект" компилятора на литералы типа AnsiString(листинг 3.21).

Листинг 3.21. Сравнение переменных типа AnsiStringкак указателей

procedure TForm1.Button3Click(Sender: TObject);

var

S1, S2: string;

begin

S1 := 'Test';

S2 := 'Test';

if Pointer(S1) = Pointer(S2) then Label1.Caption := 'Равно'

else Label1.Caption := 'He равно';

end;

В этом примере на экран будет выведено Равно. Как мы видим, указатели равны, т.е. и здесь компилятор проявил "интеллект".

Рассмотрим чуть более сложный случай (листинг 3.22).

Листинг 3.22. Сравнение переменных AnsiStringи PCharкак указателей

procedure TForm1.Button4Click(Sender: TObject);

var

P: PChar;

S: string;

var

S := 'Test';

P := 'Test';

if Pointer(S) = P then Label1.Caption := 'Равно'

else Label1.Caption := 'He равно';

end;

В этом случае указатели окажутся не равны. Действительно, с формальной точки зрения литерал типа AnsiStringотличается от литерала типа PChar: в нем есть счетчик ссылок (равный -1) и длина. Однако если забыть с существовании этой добавки, эти два литерала одинаковы: четыре значащих символа и один #0, т.е. компилятор, в принципе, мог бы обойтись одним литералом. Тем не менее на это ему "интеллекта" уже не хватило. Рассмотрим еще один пример: сравнение строк по указателям (листинг 3.23).

Листинг 3.23. Сравнение глобальных переменных типа AnsiStringкак указателей

var

GS1, GS2: string;

procedure TForm1.Button5Click(Sender: TObject);

begin

GS1 := 'Test';

GS2 := 'Test';

if Pointer(GS1) = Pointer(GS2) then Label1.Caption := 'Равно';

else Label1.Caption := 'Не равно';

end;

Этот пример отличается от приведенного в листинге 3.21 только тем, что теперь переменные глобальные, а не локальные. Однако этого достаточно, чтобы результат оказался другим — на экране мы увидим надпись Не равно. Для глобальных переменных компилятор всегда создаст уникальный литерал, на обнаружение одинаковых литералов ему "интеллекта" не хватает. Более того, если поставить точки останова в методах Button3Clickи Button4Click, легко убедиться, что указатель, который будет помещен в переменную Sв методе Button4Click, отличается от того, который будет помещен в переменные S1и S2в методе Button3Click, хотя литералы в обоих случаях одинаковые. Компилятор умеет обнаруживать равенство литералов типа AnsiStringтолько в пределах одной функции.

Теперь посмотрим, что будет с глобальными переменными типа PCharпри присваивании им одинакового литерала (листинг 3.24).

Листинг 3.24. Сравнение глобальных переменных типа PChar

var

GP1, GP2: PChar;

procedure TForm1.Button6Click(Sender: TObject);

begin

GP1 := 'Test';

GP2 := 'Test';

if GP1 = GP2 then Label1.Caption := 'Равно'

else Label1.Caption := 'He равно';

end;

После выполнения этого кода мы увидим надпись Равно, т.е. здесь компилятор смог обнаружить равенство литералов, несмотря на то, что переменные глобальные. Однако переменные типа PChar, которым присваиваются одинаковые литералы в разных функциях, как и переменные типа AnsiString, получат разные значения.

Но вернемся к сравнению строк. Как мы знаем, строки AnsiStringсравниваются по значению, а PChar— по указателю. А что будет, если сравнить AnsiStringс PChar? Ответ на этот вопрос даёт листинг 3.25.

Листинг 3.25. Сравнение переменных типа AnsiStringи PChar

procedure TForm1.Button7Click(Sender: TObject);

var

P: PChar;

S: string;

begin

S := 'Test';

P := 'Тest';

it S = Р then Label1.Caption := 'Равно'

else Label1.Caption := 'Не равно';

end;

Этот код выдаст Равно. Как мы знаем из предыдущих примеров (см. листинг 3.22), значения указателей не будут равны, следовательно, производится сравнение по содержанию, т.е. именно то, что к требуется. Если исследовать код, который генерирует компилятор, то можно увидеть, что сначала неявно создается строка AnsiString, в которую копируется содержимое строки PChar, а потом сравниваются две строки AnsiString. Сравниваются, естественно, по значению.

Для строк ShortStringсравнение указателей невозможно, две таких строки всегда сравниваются по значению. Правила хранения литералов и сравнения с другими типами следующие:

1. Литералы типа ShortStringразмещаются в сегменте кода только один раз на одну функцию, сколько бы раз они ни повторялись в ее тексте.

2. При сравнении строк ShortStringи AnsiStringпервая сначала конвертируется в тип AnsiString, а потом выполняется сравнение.

3. При сравнении строк ShortStringи PCharстрока PCharконвертируется в ShortString, затем эти строки сравниваются.

Последнее правило таит в себе «подводный камень», который иллюстрируется следующим примером (листинг 3.26).

Листинг 3.26. Ошибка при сравнении переменных типа ShortStringи PChar

procedure TForm1.Button8Click(Sender: TObject);

var

P: PChar;

S: ShortString

begin

P := StrAlloc(300);

FillChar(P^, 299, 'A');

P[299] := #0;

S[0] := #255;

FillChar(S[1], 255, 'A');

if S = P then Label1.Caption := 'Равно'

else Label1.Caption := 'Не равно';

StrDispose(Р);

end;

Здесь формируется строка типа PChar, состоящая из 299 символов "A". Затем формируется строка ShortString, состоящая из 255 символов "А". Очевидно, что эти строки не равны, потому что имеют разную длину. Тем не менее на экране появится надпись Равно.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


А. Григорьев читать все книги автора по порядку

А. Григорьев - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




О чём не пишут в книгах по Delphi отзывы


Отзывы читателей о книге О чём не пишут в книгах по Delphi, автор: А. Григорьев. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x