(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Delphi: Загадочный тип PCHAR (исходники)

Источник: programmersclub

Здравствуйте, дельфисты! Сегодня вам поведую, что это за тип PCHAR. И как его корректно использовать. Этот тип упоминается во всех API функциях, которые принимают в качестве параметра какое-либо строковое значение.

Сначала я расскажу вам про тип string. Тип string является главным преимуществом языка Pascal над языком С. Именно из-за этого типа программы, написанные на Pascal, весят больше, чем программы, написанные на С. Все знают, что тип string является массивом, котором каждый элемент является типом CHAR (следовательно, юникодовский тип WideString - массив из WideChar). Только размер этого массива неизвестен заранее и при каждом присваивании его длина изменяется. Но так же можно и при объявлении ограничить размер строки. Но размер строки ограничивается только формально, потому что нельзя обратиться к элементу массива больше чем размер строки указанной в разделе var. Конечно, размер каждой строки должен быть не более 2ГБ, примерно 2 миллиарда символов (для widestring 1 миллиард символов, так как один символ задаётся 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. Вот такими словами кончается моя очередная статья.

Руслан Аблязов


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 06.10.2006 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
VMware Horizon Apps Standard, v7 : 10 Pack (Named User)
Delphi Professional Named User
ABBYY FineReader 14 Standard Full
ZBrush 4R6 Win Commercial Single License ESD
NauDoc Enterprise 10 рабочих мест
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Компьютерные книги. Рецензии и отзывы
Adobe Photoshop: алхимия дизайна
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100