Delphi: Загадковий тип PCHAR (исходники), Різне, Програмування, статті

Привіт дельфісти! Сьогодні вам поведу, що це за тип PCHAR. І як його коректно використовувати. Цей тип згадується у всіх API функціях, які приймають як параметр-яке строкове значення.

Спочатку я розповім вам про тип string. Тип string є головною перевагою мови Pascal над мовою С. Саме через це типу програми, написані на Pascal, важать більше, ніж програми, написані на С. Всі знають, що тип string є масивом, якому кожен елемент є типом CHAR (отже, юнікодовскій тип WideString – масив з WideChar). Тільки розмір цього масиву невідомий заздалегідь і при кожному привласненні його довжина змінюється. Але так само можна і при оголошенні обмежити розмір рядка. Але розмір рядка обмежується тільки формально, тому що не можна звернутися до елементу масиву більше ніж розмір рядки зазначеної в розділі var. Звичайно, розмір кожного рядка повинен бути не більше 2ГБ, приблизно 2000000000 символів (для widestring 1000000000 символів, так як один символ задається 2 байтами). Так як рядок це масив, отже, через квадратні дужки можна звертатися до кожного елементу масиву.

Str:=”programmersclub.ru”;
Str[1]:=”P”;
Str[5]:=”L”;

Після даних маніпуляцій мінлива str дорівнюватиме “ProgLammersclub.ru”, зауважу, що перший символ в рядку має індекс 1. Так як тип string і тип array of char подібні слідчий їх можна присвоїти один до одного. Але, при присвоєнні змінної масиву змінної рядка буде помилка, так як у масиву ми жорстко ставимо розмір масиву, а у рядки ми не знаємо довжину навіть при її обмеженні.

Var
STR_ARR: ARRAY[1..60] of CHAR;
STR1:Srring;
STR2:String[20];
Begin
………………
STR_ARR: = str1 ;/ / помилка
Str1:=STR_ARR:
Str2: = STR_ARR ;/ / ні помилки

Звертатися до 55 символу змінної str2 вже не можна, але фізично в пам’яті він існує. При отриманні покажчика на рядок повертається адресу першого символу в рядку, значить, такі висловлювання однакові:

P1:=@str;
P2:=@str[1];

Тепер тип PCHAR. Фактично тип PCHAR це покажчик на тип CHAR. Це зрозуміло і тому як він названий. По “программескім” правилам при оголошенні нового типу типізованих покажчиків береться тип, на який вказує покажчик і спереду ставиться буква P. Ось його оголошення:

Type
PCHAR: ^ CHAR ;/ / отже також і тип WideChar
PWIDECHAR: ^ WIDECHAR;

Ну, якщо цей тип вказує на тільки один символ, то, як же функції розуміють параметри, які ми передаємо їм. Все дуже просто. Кожен рядок, передана в якості параметра який або функції повинна мати в кінці символ # 0. Функція за вказівником знаходить перший символ рядка і йде далі поки не наткнеться на символ # 0. Delphi автоматизувала перетворення рядка коли в параметрі ми вказуємо саму рядок: MessageBox (0, “привіт”, “привіт”, 0) тут автоматика, а чому не автоматика при вказування змінних я не знаю. Ми завжди пишемо

MessageBox(0,pchar(str),pchar(str),0);

Все нормально. Той же результат при використанні покажчиків.

MessageBox(0,@str,@str,0);

Це тому що масиви зазвичай заповнюються нулями.
Приклад 1:
Зовсім інша історія:

var
STR_ARR:array[1..2] of char;
STR:String[6];
begin
str_ARR[1]:=”h”;
str_ARR[2]:=#0;
STR:=”22″+#0;
MessageBoxA(Handle,@STR,@str_ARR,MB_OK);

У повідомленні перед двійкою варто якийсь символ. Це тому що нумерація в Delphi може починатися з будь-якого індексу, в даному випадку вона починається 1, а 0 символ не використовується. Значить те, що я вам сказав на початку це неправильно:
P1:=@str;
P2: = @ str [1]; / / ці покажчики будуть відрізнятися на 1;

А масив виводиться нормально, тому що Delphi автоматично править покажчик на масив.
Приклад 2:

Не знаю чому, але замість двійок виводиться не зрозумій що. Містика!

var
STR_ARR:array[1..2] of char;
STR: String; / / будь-яка довжина
begin
str_ARR[1]:=”h”;
str_ARR[2]:=#0;
STR:=”22″+#0;
MessageBoxA(Handle,@STR,@str_ARR,MB_OK);
Приклад 3:
var
STR_ARR:array[1..2] of char;
STR:String[4];
begin
str_ARR[1]:=”h”;
str_ARR[2]:=#0;
STR:=”22″;
MessageBoxA(Handle,@STR,@str_ARR,MB_OK);

Звідси зрозуміло що спочатку всі змінні заповнюються нулями. І мінлива STR тому не виключення.
Приклад 4:
Цікава ситуація:
var
STR_ARR:array[1..2] of char;
STR:String[4];
begin
str_ARR[1]:=”h”;
str_ARR[2]:=”s”;
STR:=”22″+#0;
MessageBoxA(Handle,@STR,@str_ARR,MB_OK);

Як бачите в заголовку є символи “hs” потім квадратик потім двійки. Всьому є розумне пояснення. Рядок STR_ARR не кінчається нулем, отже, функція не знайшла нуль тільки в кінці рядка STR_ARR і пішла далі до змінної STR, тому рядок STR_ARR вийшла такою довгою. Квадратик в після рядка “hs” зрозумілий з першого прикладу.

Ось такі пироги. Спочатку здавалося, що тип string простіше і краще, а вийшло як завжди! Тип string приніс нам масу неприємностей. Тому C + + набагато популярніше Delphi. Ось такими словами закінчується моя чергова стаття.
Руслан Аблязов

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*