MyBooks.club
Все категории

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

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая А. Григорьев - О чём не пишут в книгах по Delphi. Жанр: Программирование издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
О чём не пишут в книгах по Delphi
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
17 сентябрь 2019
Количество просмотров:
245
Читать онлайн
А. Григорьев - О чём не пишут в книгах по Delphi

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

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

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

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

Начнем со сравнения двух строк типа PChar (листинг. 3.19).

Листинг 3.19. Сравнение строк типа PChar

procedure TForm1.Button1Click(Sender: TObject);

var

 P1, P2: PChar;

begin

 P1 := StrNew('Test');

 P2 := StrNew('Test');

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

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

 StrDispose(P1);

 StrDispose(P2);

end;

В данном примере мы увидим надпись Не равно. Это происходит потому, что в этом случае сравниваются указатели, а не содержимое строк, а указатели здесь будут разные. Попытка сравнить строки с помощью оператора сравнения — весьма распространенная ошибка у начинающих. Для сравнения таких строк следует применять специальную функцию — StrComp. Следующий пример, на первый взгляд, в плане сравнения ничем не отличается от только что рассмотренного (листинг 3.20).

Листинг 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 символов "А". Очевидно, что эти строки не равны, потому что имеют разную длину. Тем не менее на экране появится надпись Равно.

Происходит это вот почему: строка PChar оказывается больше, чем максимально допустимый размер строки ShortString. Поэтому при конвертировании лишние символы просто отбрасываются. Получается строка длиной 255 символов, совпадающая со строкой ShortString, с которой мы ее сравниваем. Отсюда вывод: если строка ShortString содержит 255 символов, а строка PChar — более 255 символов, и ее первые 255 символов совпадают с символами строки ShortString, операция сравнения ошибочно даст положительный результат, хотя эти строки не равны.

Избежать этой ошибки поможет либо явное сравнение длины перед сравнением строк, либо приведение одной из сравниваемых строк к типу AnsiString (второй аргумент при этом также будет приведен к этому типу). Следующий пример (листинг 3.27) дает правильный результат Не равно.


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

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


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

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

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.