Последние записи
- Преобразовать массив байт в вещественное число (single)
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
- Взаимодействие через командную строку
- Перенести программу из Delphi в Lazarus
- Определить текущую ОС
- Автоматическая смена языка (раскладки клавиатуры)
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
29th
Авг
Загадочный тип PCHAR (delphi)
Posted by Chas under Статьи
Здравствуйте, дельфисты! Сегодня вам поведую, что это за тип 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. Вот такими словами кончается моя очередная статья.
Руслан Аблязов E-mail
Похожие статьи
Купить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)