WideChar — Тип Delphi


Содержание

Загадочный тип PCHAR

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

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

После данных манипуляций переменная str будет равна ‘ProgLammersclub.ru’, замечу, что первый символ в строке имеет индекс 1. Так как тип string и тип array of char сходны следователь их можно присвоить друг к другу. Но, при присваивании переменной массива переменной строки будет ошибка, так как у массива мы жёстко задаём размер массива, а у строки мы не знаем длину даже при её ограничении.

Обращаться к 55 символу переменной str2 уже нельзя, но физически в памяти он существует. При получении указателя на строку возвращается адрес первого символа в строке, значит, такие выражения одинаковы:

Теперь тип PCHAR. Фактически тип PCHAR это указатель на тип CHAR. Это понятно и потому как он назван. По «программеским» правилам при объявлении нового типа типизированных указателей берётся тип, на который указывает указатель и спереди ставится буква P. Вот его объявление:

Ну, если этот тип указывает на только один символ, то, как же функции понимают параметры, которые мы передаём им. Всё очень просто. Каждая строка, переданная в качестве параметра какой либо функции должна иметь в конце символ #0. Функция по указателю находит первый символ строки и идёт дальше пока не наткнётся на символ #0. Delphi автоматизировала преобразование строки когда в параметре мы указываем саму строку: MessageBox(0,’привет’,’привет’,0) здесь автоматика, а почему не автоматика при указывании переменных я не знаю. Мы всегда пишем

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

Это потому что массивы обычно заполняются нулями.

Пример 1: Совсем другая история:

В сообщении перед двойкой стоит какой то символ. Это потому что нумерация в Delphi может начинаться с любого индекса, в данном случае она начинается 1, а 0 символ не используется. Значит то, что я вам сказал в начале это неправильно:

А массив выводится нормально, потому что Delphi автоматически правит указатель на массив.

Пример 2: Не знаю почему, но вместо двоек выводится не пойми что. Мистика.

Отсюда понятно что изначально все переменные заполняются нулями. И переменная STR тому не исключение.

Пример 4: Интересная ситуация:

Как видите в заголовке есть символы ‘hs’ потом квадратик потом двойки. Всему есть разумное объяснение. Строка STR_ARR не кончается нулём, следовательно, функция не нашла нуль только в конце строки STR_ARR и пошла дальше к переменной STR, поэтому строка STR_ARR получилась такой длинной. Квадратик в после строки ‘hs’ понятен из первого примера.

Вот такие пироги. Изначально казалось, что тип string проще и лучше, а получилось как всегда! Тип string принёс нам массу неприятностей. Поэтому C++ намного популярнее Delphi. Вот такими словами кончается моя очередная статья.

В чем разница между W >

Я обновляю некоторый древний (с 2003 года) код Delphi до Delphi Architect XE, и у меня возникают некоторые проблемы. Я получаю ряд ошибок, когда есть несовместимые типы. Эти ошибки не происходят в Delphi 6, поэтому я должен предположить, что это потому, что вещи были обновлены.

Честно говоря, я не знаю, в чем разница между PAnsiChar и PWideChar, но Delphi точно знает разницу и не даст мне скомпилировать. Если бы я знал, в чем заключаются различия, возможно, я мог бы выяснить, что использовать или как это исправить.

2 ответа

Коротко: до Delphi 2009 нативный тип строки в Delphi имел обыкновение быть ANSI CHAR: каждый символ в каждой строке был представлен как 8-битный символ. Начиная с Delphi 2009, строки Delphi стали UNICODE с использованием нотации UTF-16: теперь базовый Char использует 16 бит данных (2 байта), и вам, вероятно, не нужно много знать о кодовых точках Unicode, которые представлены в виде двух последовательные 16-битные символы.

8-битные символы называются «анси-символы». PAnsiChar — это указатель на 8-битные символы. 16-битные символы называются «широкими символами». PWideChar — это указатель на 16-битные символы. Delphi знает разницу и преуспевает, если не позволяет вам смешивать оба!

Больше информации

Вы можете найти более подробную информацию о переносе Delphi в Unicode здесь: Новая Белая книга: Миграция Delphi Unicode для простых смертных

Вы также можете найти SO для «Миграция Delphi Unicode».

Пару лет назад тип символов по умолчанию в Delphi был изменен с AnsiChar (однобайтовая переменная, представляющая символ ANSI) на WideChar (двухбайтовая переменная, представляющая символ UTF16.) Тип char теперь является псевдонимом WideChar вместо AnsiChar тип string теперь является псевдонимом UnicodeString (версия Unicode UTF-16 традиционного типа строки Delphi) вместо AnsiString , а тип PChar теперь является псевдонимом PWideChar вместо PAnsiChar .

Компилятор может сам позаботиться о многих преобразованиях, но есть несколько проблем:

  1. Если вы используете типы строковых указателей, такие как PChar , вам нужно убедиться, что указатель указывает на правильный тип данных, и компилятор не всегда может это проверить.
  2. Если вы передаете строки в параметры var , тип переменной должен быть точно таким же. Это может быть более сложным теперь, когда у вас есть два типа строк для работы.
  3. Если вы используете string как удобный буфер байтового массива для хранения произвольных данных вместо переменной, содержащей текст, это не будет работать как UnicodeString . Убедитесь, что они объявлены как RawByteString как обходной путь.
  4. Везде, где вы имеете дело с длиной строки в байтах, например, при чтении или записи в / из TStream, убедитесь, что ваш код не предполагает, что длина char составляет один байт.

Взгляните на Delphi Unicode Migration for Mere Mortals, чтобы узнать о некоторых хитростях и советах, как заставить это работать. Это не так сложно, как кажется, но и не тривиально. Удачи!

WideChar — Тип Delphi

Профиль
Группа: Завсегдатай
Сообщений: 3439
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60

Код
var CompName: PWideChar;
begin
edit1.text := ‘192.168.172.229’;
CompName := PWideChar(edit2.text);
showmessage(CompName);
end;

Профиль
Группа: Модератор
Сообщений: 11360
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 483

Snowy
Дата 20.11.2006, 11:22 (ссылка) | (нет голосов) Загрузка .
Код
CompName := PWideChar(WideString(edit2.text));

Профиль
Группа: Завсегдатай
Сообщений: 3439
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60

Cashey
Дата 20.11.2006, 11:26 (ссылка) | (нет голосов) Загрузка .

Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 17
Всего: 50

Matematik
Дата 20.11.2006, 11:26 (ссылка) | (нет голосов) Загрузка .
Google
Дата 12.11.2020, 00:39 (ссылка)

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) — крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

Несовместимые типы: «WideChar» и «Чара» Дельфи 7

Я получаю сообщение об ошибке в моем DELPHI коды при использовании ShellExecute для вызова внешнего progrem

как я reslve этой ошибки?

ShellExecute Функция определяется как так

Таким образом, вопрос , который вы заливка args переменного к PWideChar вместо PChar .

Попробуйте этот код

Помните , что Delphi 7 до даты разработки Unicode Delphi. И так PChar это псевдоним для 8 битного типа символов PAnsiChar .

Типы данных Delphi

Теперь обсудим типы данных Delphi, которые программист использует при написании программы. Любая программа на Delphi может содержать данные многих типов:

  • целые и дробные числа,
  • символы,
  • строки символов,
  • логические величины.

Целый тип Delphi

Библиотека языка Delphi включает в себя 7 целых типов данных: Shortint, Smallint, Longint, Int64, Byte, Word, Longword, характеристики которых приведены в таблице ниже.

Вещественный тип Delphi

Кроме того, в поддержку языка Delphi входят 6 различных вещественных типов (Real68, Single, Double, Extended, Comp, Currency), которые отличаются друг от друга, прежде всего, по диапазону допустимых значений, по количеству значащих цифр, по количеству байт, которые необходимы для хранения некоторых данных в памяти ПК (характеристики вещественных типов приведены ниже). Также в состав библиотеки языка Delphi входит и наиболее универсальный вещественный тип — тип Real, эквивалентный Double.

Символьный тип Delphi

Кроме числовых типов, язык Delphi располагает двумя символьными типами:

Тип Ansichar — символы c кодировкой ANSI, им ставятся в соответствие числа от 0 до 255;

Тип Widechar — символы с кодировкой Unicode, им ставятся в соответствие числа от 0 до 65 535.

Строковый тип Delphi

Строковый тип в Delphi обозначается идентификатором string. В языке Delphi представлены три строковых типа:

Тип Shortstring — присущ статически размещаемым в памяти ПК строкам, длина которых изменяется в диапазоне от 0 до 255 символов;

Тип Longstring — этим типом обладают динамически размещаемые в памяти ПК строки с длиной, ограниченной лишь объемом свободной памяти;

Тип WideString — тип данных, использующийся для того, чтобы держать необходимую последовательность Интернациональный символов, подобно целым предложениям. Всякий символ строки, имеющей тип WideString, представляет собой Unicode-символ. В отличие от типа Shortstring, тип WideString является указателем, который ссылается на переменные.

Логический тип Delphi

Логический тип соответствует переменным, которые могут принять лишь одно из двух значений: true, false. В языке Delphi логические величины обладают типом Boolean. Вам были представлены основные типы данных Delphi. Движемся дальше.

What is the difference between W > Ask Question

I’m upgrading some ancient (from 2003) Delphi code to Delphi Architect XE and I’m running into a few problems. I am getting a number of errors where there are incompatible types. These errors don’t happen in Delphi 6 so I must assume that this is because things have been upgraded.

I honestly don’t know what the difference between PAnsiChar and PWideChar is, but Delphi sure knows the difference and won’t let me compile. If I knew what the differences were maybe I could figure out which to use or how to fix this.

2 Answers 2

The short: prior to Delphi 2009 the native string type in Delphi used to be ANSI CHAR: Each char in every string was represented as an 8 bit char. Starting with Delphi 2009 Delphi’s strings became UNICODE, using the UTF-16 notation: Now the basic Char uses 16 bits of data (2 bytes), and you probably don’t need to know much about the Unicode code points that are represented as two consecutive 16 bits chars.

The 8 bit chars are called «Ansi Chars». An PAnsiChar is a pointer to 8 bit chars. The 16 bit chars are called «Wide Chars». An PWideChar is a pointer to 16 bit chars. Delphi knows the difference and does well if it doesn’t allow you to mix the two!

More info

You can find some more information on migrating Delphi to Unicode here: New White Paper: Delphi Unicode Migration for Mere Mortals

You may also search SO for «Delphi Unicode migration».

A couple years ago, the default character type in Delphi was changed from AnsiChar (single-byte variable representing an ANSI character) to WideChar (two-byte variable representing a UTF16 character.) The char type is now an alias to WideChar instead of AnsiChar , the string type is now an alias to UnicodeString (a UTF-16 Unicode version of Delphi’s traditional string type) instead of AnsiString , and the PChar type is now an alias to PWideChar instead of PAnsiChar .

The compiler can take care of a lot of the conversions itself, but there are a few issues:

  1. If you’re using string-pointer types, such as PChar , you need to make sure your pointer is pointing to the right type of data, and the compiler can’t always verify this.
  2. If you’re passing strings to var parameters, the variable type needs to be exactly the same. This can be more complicated now that you’ve got two string types to deal with.
  3. If you’re using string as a convenient byte-array buffer for holding arbitrary data instead of a variable that holds text, that won’t work as a UnicodeString . Make sure those are declared as RawByteString as a workaround.
  4. Anyplace you’re dealing with string byte lengths, for example when reading or writing to/from a TStream, make sure your code isn’t assuming that a char is one byte long.

Take a look at Delphi Unicode Migration for Mere Mortals for some more tricks and advice on how to get this to work. It’s not as hard as it sounds, but it’s not trivial either. Good luck!

Несовместимые типы: ‘PAnsiChar’ и ‘PW >

этот вопрос уже есть ответ здесь:

Я очень новичок в delphi XE8. У меня есть следующий код, который из моей версии delphi 6, и я хочу запустить его в delphi XE8.


когда я пытаюсь запустить его, ошибка указывает на строки 8 и 25 в коде с сообщением об ошибке

у меня поиск везде для решения, но я просто не могу решить проблему. Пожалуйста помочь.. Спасибо.

2 ответов

в Delphi 2007 и более ранних, PChar псевдоним PAnsiChar . В Delphi 2009 и выше, PChar псевдоним PWideChar . Таким образом, изменяя компилятор, вы изменяете значение кода.

вы можете решить эту проблему, просто заменив PChar с PAnsiChar и код будет иметь свое первоначальное значение.

в современном Unicode Delphi было бы более естественно использовать string (псевдоним UnicodeString ) вместо COM WideString . Вы также можете использовать один из многих библиотек процедуры для выполнения преобразования UTF-8.

там, безусловно, будут другие вопросы впереди вас. Я рекомендую вам прочитать белый лист Марко Канту на Unicode в Delphi как твой следующий шаг.

LPCSTR
Указатель на постоянную строку с нулевым завершением 8-разрядных окон (в ANSI) символов.
Этот тип объявлен в WinNT.H следующим образом:
typedef __nullterminated CONST CHAR *LPCSTR;

LPSTR
Указатель на строку с нулевым завершением 8-разрядных окон (в ANSI) символов.
Этот тип объявлен в WinNT.H следующим образом:
typedef CHAR *LPSTR;

проблемы, связанные с вашим кодом заключается в том, что аргумент lpMultiByteStr каждой функции PAnsiChar и вы проезжаете PChar в качестве параметра.
на PChar — это псевдоним из PAnsiChar на Delphi 6 и стоит PWideChar на Дельфи X Е8.

вы можете решить эту проблему в строке #8, объявив вам функцию (и вызвав ее соответственно) следующим образом:
function UTF8ToStringLen(const src: PAnsiChar; const Len: Cardinal): WideString;

чтобы решить проблему в строке #25, измените объявление функции, например:
function StringToUTF8Len(const src: PAnsiChar; const Len: Cardinal): string;
и «пресловутого» строку:
bsiz := WideCharToMultiByte(CP_UTF8, 0, PWideChar(Temp), -1, PAnsiChar(Result), bsiz, nil, nil);

Несовместимые типы: «WideChar» и «Чара» Дельфи 7

Я получаю сообщение об ошибке в моем DELPHI коды при использовании ShellExecute для вызова внешнего progrem

как я reslve этой ошибки?

ShellExecute Функция определяется как так

Таким образом, вопрос , который вы заливка args переменного к PWideChar вместо PChar .

Попробуйте этот код

Помните , что Delphi 7 до даты разработки Unicode Delphi. И так PChar это псевдоним для 8 битного типа символов PAnsiChar .

Символьный тип

Язык Delphi поддерживает два символьных типа: Ansichar и Widechar:

  • тип Ansichar — это символы в кодировке ANSI, которым соответствуют числа в диапазоне от 0 до 255;
  • тип widechar — это символы в кодировке Unicode, им соответствуют числа от 0 до 65 535.

Object Pascal поддерживает и наиболее универсальный символьный тип — Char, который эквивалентен Ansichar.

Правила форума «Delphi: Общие вопросы»

НОВОСТИ ФОРУМА
Рыцари теории эфира
01.10.2020 — 05:20: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]69vJGqDENq4[/Youtube][/center]
[center]14:36[/center]
Osievskii Global News
29 сент. Отправлено 05:20, 01.10.2020 г.’ target=_top>Просвещение от Вячеслава Осиевского — Карим_Хайдаров.
30.09.2020 — 12:51: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Ok]376309070[/Ok][/center]
[center]11:03[/center] Отправлено 12:51, 30.09.2020 г.’ target=_top>Просвещение от Дэйвида Дюка — Карим_Хайдаров.
30.09.2020 — 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]VVQv1EzDTtY[/Youtube][/center]
[center]10:43[/center]

интервью Раввина Борода https://cursorinfo.co.il/all-news/rav.
мой телеграмм https://t.me/peshekhonovandrei
мой твиттер https://twitter.com/Andrey54708595
мой инстаграм https://www.instagram.com/andreipeshekhonow/

[b]Мой комментарий:
Андрей спрашивает: Краснодарская синагога — это что, военный объект?
— Да, военный, потому что имеет разрешение от Росатома на манипуляции с радиоактивными веществами, а также иными веществами, опасными в отношении массового поражения. Именно это было выявлено группой краснодарцев во главе с Мариной Мелиховой.

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

WideChar — Тип Delphi

В этой статье рассказывается о том, что Вам нужно сделать, чтобы подготовить свой код к Delphi 2009.

В Части I этой серии было сказано, что Delphi 2009 по умолчанию будет использовать строку, основанную на UTF-16. В результате некоторые части существующего кода могут потребовать изменений. В основном, большая часть существующего кода будет прекрасно работать в Delphi 2009. Как Вы увидите, основные изменения в коде касаются только очень специфических, даже эзотерических, моментов. Как бы там ни было, нужно рассмотреть те особые части кода, которые, скорее всего, придется редактировать. Также нужно будет проверить результаты работы такого кода, чтобы убедиться, что он правильно работает с UnicodeString.

Например, любой код, работающий со строками и выполняющий операции с указателями на них, должен быть изучен на совместимость с Юникодом. Говоря более конкретно, любой код:

  • считающий, что SizeOf(Char)=1;
  • считающий, что длина строки равна количеству байт в строке;
  • который пишет и читает строки из какого-либо постоянного хранилища или использует строку как буфер для данных

должен быть проанализирован, чтобы убедиться, что эти особенности не влияют на работу. Код, который пишет и читает из какого-либо постоянного хранилища, должен быть проверен на то, что считывается или пишется правильное количество байт, так как один байт больше не является одним символом.

Как правило, любые изменения в коде являются достаточно простыми и могут быть сделаны с минимальными усилиями.

Части, которые должны «работать прямо так»

Здесь рассказывается о тех частях кода, которые будут продолжать работать и не потребуют никаких изменений для корректной работы с новой UnicodeString. VCL и RTL были полностью обновлены, чтобы работать в Delphi 2009 так, как и всегда. С маленькими-маленькими оговорками так оно и есть. К примеру, TStringList теперь полностью поддерживает Юникод, и весь существующий код, в котором используется TStringList, должен работать так же, как и раньше. Кроме того, TStringList был улучшен для работы специально с Юникодом, поэтому если Вы хотите использовать новую функциональность, Вы можете это сделать, но если это Вам не нужно — можете вообще о ней не думать.

Обычное использование строковых типов

В основном, код, использующий строковый тип, будет работать, как и прежде. Нет необходимости переобъявлять строковые переменные в тип AnsiString, за исключением тех случаев, которые описаны ниже. Объявления строк должны быть изменены на AnsiString во всех местах, где строки используются в качестве буфера для данных.

Runtime Library

Дополнения к Runtime Library были подробно рассмотрены в Части II.

В той статье не упоминался новый модуль, добавленный в RTL — AnsiString.pas. Этот модуль существует для обратной совместимости с кодом, который использует или требует для своей работы AnsiString.


Код Runtime Library выполняется как обычно, и в основном не требует изменений. Части, которые нужно изменить, описаны ниже.

Вся VCL поддерживает Юникод. Все существующие VCL-компоненты работают с момента установки, как всегда и было. Практически весь код, использующий VCL, будет нормально работать. Мы проделали огромную работу, чтобы быть уверенными, что VCL совместим как со старым кодом, так и с Юникодом. Обычный VCL-код, не выполняющий никаких особенных манипуляций со строками, будет работать как и раньше.

Индексация в строках

Индексация в строках работает точно так же, как и прежде, поэтому код, индексирующий элементы строк, не требует изменений:

Length/Copy/Delete/SizeOf для строк

Функция Copy будет работать, как всегда, без изменений. То же самое относится к Delete и всем остальным процедурам работы со строками, основанными на SysUtils.

Вызов Length(SomeString), как и всегда, вернет количество элементов в переданной строке.

Вызов SizeOf для любого идентификатора строки вернет 4, так как все строковые объявления — это ссылки и размер указателя равен 4.

Вызов Length для любой строки вернет количество элементов в этой строке.

Рассмотрим следующий код:

В результате его выполнения будет выведено следующее:

Работа с указателями для PChar

Работа с указателями для PChar будет выполняться, как и раньше. Компилятору известен размер PChar, поэтому код, подобный приведенному ниже, будет работать, как и ожидается:

Этот код будет работать точно так же, как и в предыдущих версиях Delphi, но, конечно, с другими типами данных: PChar это теперь PWideChar и MyString — это теперь UnicodeString.

ShortString

ShortString осталась неизменной, как по функциям, так и по объявлению, она будет работать, как и раньше.

Объявления ShortString выделяют буфер для заданного количества AnsiChar»ов. Такой код:

выведет на экран следующее:

Обратите внимание, что общий размер алфавита — 26, это говорит о том, что переменная содержит AnsiChar»ы.

Рассмотрим также и такой код:

Это запись будет расположена в памяти точно так же, так и раньше — это будет запись из двух AnsiString»ов, содержащих AnsiChar»ы. Если у Вас есть File of Rec из записей, содержащих ShortString»и, то приведенный выше код будет работать, как и раньше, и любое чтение или запись не потребует никаких изменений.

Однако помните, что Char — это теперь WideChar, поэтому если Вы используете код, который читает такие записи из файла и потом делаете что-то вроде:

то Вы должны помнить, что SomeChar превратит AnsiChar в String1[3] в WideChar. Если Вам нужно, чтобы этот код работал, как раньше, измените объявление SomeChar:

Части, которые должны быть проверены

В этой части статьи описаны различные конструкции, которые должны быть проверены в существующем коде для совместимости с Юникодом. Поскольку Char теперь является WideChar, данные о байтовом размере символьного массива или строки могут быть неверными. Ниже приведены несколько примеров конструкций кода, которые нужно изучить, чтобы убедиться в их совместимости с новым типом UnicodeString.

SaveToFile/LoadFromFile

Вызовы SaveToFile и LoadFromFile можно было бы отнести к предыдущей части статьи (Части, которые должны «работать прямо так»), если бы они выполняли чтение и запись так же, как они делали это раньше. Однако Вам может понадобиться использование новых перегруженных версий этих процедур, если Вы решили работать с Юникод-данными.

К примеру, TStrings теперь включает следующий набор перегруженных методов:

Второй метод — это новая перегрузка, принимающая кодировку в качестве параметра, который задает, каким образом данные будут записаны в файл. (В Части II Вы можете прочитать описание типа TEncoding.) Если Вы вызовете первый метод, строковые данные будут записаны так же, как это делалось обычно — как ANSI-данные. Благодаря этому уже существующий код будет работать точно так же, как и всегда.

Однако если Вам нужно записать текст в формате Юникод, то нужно вызвать второй вариант метода, передав ему в параметре соответствующее значение типа TEncoding. Если не сделать этого, строки будут записаны как ANSI-данные, что, скорее всего, приведет к потере информации.

Таким образом, наилучший способ в этом случае — проанализировать вызовы SaveToFile и LoadFromFile и добавить к ним второй параметр, чтобы показать, каким образом нужно сохранить или загрузить данные. Если Вы считаете, что никогда не будете добавлять или использовать Юникод-строки, то можете оставить все, как есть.

Использование функции Chr

Существующий код, превращающий значение типа integer в Char может использовать функцию Chr. Это может привести к следующей ошибке:

Если в коде, использующем функцию Chr, имеется присвоение ее результата переменной типа AnsiChar, то эту ошибку можно легко исключить, заменив функцию Chr преобразованием в тип AnsiChar.

То есть, такой код:

можно заменить таким:

Символьные множества

Наверное, самой распространенной идиомой, которая может создать проблемы компилятору, является использование символов в множествах. Раньше, когда символ занимал один байт, хранение символов в множествах не создавало никаких трудностей. Но теперь Char объявлен как WideChar, и поэтому больше не может храниться в множестве. Поэтому, если у Вас есть код наподобие этого:

и Вы скомпилируете его, то получите предупреждение, которое будет выглядеть примерно так:

Если хотите, можете оставить код неименным — компилятор будет «знать», что Вы пытаетесь сделать и сгенерирует правильный код. Однако, если Вы хотите избавиться от этого предупреждения, то можете использовать новую функцию CharInSet:

Функция CharInSet вернет булевское значение и код скомпилируется без предупреждений компилятора.

Использование строк в качестве буферов данных

Часто при работе с данными строки используются как буферы. Это делается часто, потому что это просто — работа со строками проста и понятна. Однако, существующий код, который так делает, в большинстве случаев потребует дополнительной настройки, исходя из того, что string это теперь UnicodeString.

Есть несколько способов разобраться с кодом, который использует строки как буферы данных. Первый — это просто объявить переменную, используемую в качестве буфера, как AnsiString вместо string. Если для работы с байтами буфера в коде используются Char»ы — объявите эти переменные как AnsiChar. Если Вы выберете этот путь, весь Ваш код будет работать, как и прежде, но Вы должны помнить: все переменные, работающие с таким строковым буфером, должны быть ANSI-типа.

Второй, более верный путь, — это преобразовать Ваш буфер из строкового типа в массив байтов или TBytes. Тип TBytes был создан специально для этой цели и работает так же, как и раньше, если использовался тип string.

Вызов SizeOf для буферов

Вызов SizeOf при использовании символьных массивов должен быть проверен на корректность. Рассмотрим следующий код:

Вот что этот код выведет в Memo1:

В этом коде Length вернет количество символов в данной строке (плюс терминальный символ), а SizeOf вернет количество байтов, использованных этим массивом, в данном случае 34, то есть по два байта на символ. В предыдущих версиях Delphi этот код вернул бы 17 в обоих случаях.


Использование FillChar

Вызов FillChar также нужно проверить при работе со строками и символами. Рассмотрим следующий код:

Length возвращает размер в символах, но FillChar ожидает, что Count будет в байтах. В этом случае вместо Length нужно использовать SizeOf (или нужно умножить Length на размер Char).

Кроме того, так как по умолчанию размер Char равен 2, FillChar заполнит строку байтами, а не символами, как раньше.

Это заполнит массив символами с кодом не $09, а $0909. Чтобы получить прежний результат, код нужно изменить:

Использование буквенных символов

распознает символ Евро и в итоге даст True в большинстве кодовых страниц ANSI. Однако в Delphi 2009 он даст False, так как #128 — это символ Евро в большинстве ANSI-страниц, а в Юникоде это — управляющий символ. В Юникоде символом Евро имеет код #$20AC.

При переходе на Delphi 2009 разработчикам следует заменить все коды символов со #128 по #255 на их буквенные значения, тогда:

будет работать так же, как #128 в ANSI, но будет нормально функционировать (то есть распознавать символ Евро) в Delphi 2009 (где ‘€’ имеет код #$20AC)

Использование Move

Следует проанализировать использование функции Move при работе со строками или символьными массивами. Рассмотрим следующий код:

Length возвращает размер в символах, но Move ожидает, что Count будет в байтах. В этом случае вместо Length нужно использовать SizeOf (или нужно умножить Length на размер Char).

Методы Read/ReadBuffer для TStream

Вызов TStream.Read/ReadBuffer также следует рассмотреть, если используются строки или символьные массивы. Рассмотрим следующий код:

Примечание: работа зависит от формата читаемых данных. Смотрите описание нового класса TEncoding, приведенное выше, для получения сведений о правильном кодировании текста в Stream»е.

Write/WriteBuffer

Как и в случае Read/ReadBuffer, использование TStream.Write/WriteBuffer следует проверить, если используются строки или символьные массивы. Рассмотрим следующий код:

Примечание: работа зависит от формата читаемых данных. Смотрите описание нового класса TEncoding, приведенное выше, для получения сведений о правильном кодировании текста в Stream»е.

LeadBytes

Замените такой код:

использованием функции IsLeadChar:

TMemoryStream

В тех случаях, когда для записи текста в файл используется TMemoryStream, важной является запись Byte Order Mark (BOM) в качестве начальных данных файла. Вот пример записи BOM в файл:

TStringStream

TStringStream теперь происходит от нового типа TByteStream. TByteStream добавляет свойство Bytes, дающее прямой доступ к байтам из TStringStream. TStringStream продолжает работать, как и всегда, за исключением того, что строка, которую он хранит, теперь является Юникод-строкой.

MultiByteToWideChar

Вызовы MultiByteToWideChar можно просто убрать и заменить простым присвоением. Пример использования MultiByteToWideChar:

А после перехода к Юникоду этот код был изменен, чтобы компилироваться как для ANSI, так и для Юникода:

SysUtils.AppendStr

Этот метод может использовать только AnsiString, нет его перегруженной версии для UnicodeString.

Замените вызовы вроде этого:

Или, еще лучше, используйте новый класс TStringBuilder для соединения строк.

GetProcAddress

При вызове GetProcAddress всегда следует использовать PAnsiChar (в SDK нет функции с суффиксом «W»). Например:

Примечание: Windows.pas содержит перегруженный метод, который выполняет это преобразование.

Использование преобразований к PChar() для работы с указателями при указании на не символьные типы

В предыдущих версиях не все типизированные указатели поддерживали арифметические операции. Из-за этого для выполнения арифметических операций над такими указателями они преобразовывались к PChar. В Delphi 2009 арифметика для указателей может быть включена директивой компилятора и она специально включена для типа PByte. Таким образом, если у Вас есть подобный код, преобразующий указатель к PChar для выполнения арифметических операций над ним:

В приведенном выше куске кода Node не содержит символьных данных. Он преобразовывается к PChar только для доступа к данным, расположенным через заданное число байт после Node. Раньше это работало, так как SizeOf(Char) = SizeOf(Byte). Теперь это работать не будет. Чтобы сделать работу кода правильной, следует использовать PByte вместо PChar. Если оставить все без изменений, Result будет указывать на некорректные данные.

Параметры с вариантными массивами

Если Ваш код использует TVarRec для работы с параметром — вариантным массивом — возможно, Вам придется отредактировать его для работы с UnicodeString. Для этого теперь есть новый тип vtUnicodeString, хранящий данные из UnicodeString. Рассмотрим следующий кусок из DesignIntf.pas, показывающий, в каком случае следует добавить новый код для работы с UnicodeString.

CreateProcessW

Юникод-версия CreateProcess (CreateProcessW) работает немного иначе, нежели ANSI-версия. Цитата MSDN из описания параметра lpCommandLine:

«Юникод-версия это функции, CreateProcessW, может изменить содержимое этой строки. Таким образом, этот параметр не может указывать на память только-для-чтения (то есть быть константной переменной или символьной строкой). Если этой параметр — константа, функция может вызвать ошибку доступа.»

Из-за этого существующий код, вызывающий CreateProcess, может начать выдавать ошибки доступа (Access Violations) после компиляции в Delphi 2009.

Примеры такого кода:

Передача строковой константы


Передача константного выражения


Передача строки с числом ссылок (Reference Count) -1:


Код для проверки

Вот список возможных мест в коде, которые Вам следует найти, чтобы проверить, готов ли Ваш код к правильному использованию Юникода:

  • найти любое использование «of Char» или «of AnsiChar», чтобы проверить, что буферы корректно работают с Юникодом;
  • найти «string[» и проверить, что символ, полученный по ссылке, заносится в Char (то есть в WideChar).
  • проверить неявную работу с AnsiString, AnsiChar и PAnsiChar, убедиться, что она по-прежнему нужна и правильно работает;
  • найти неявное использование ShortString, убедиться, что оно по-прежнему требуется и правильно работает;
  • найти вызовы Length( и проверить, чтобы там не подразумевалось, что Length это то же самое, что SizeOf;
  • найти вызовы Copy(, Seek(, Pointer(, AllocMem( и GetMem( и проверить, чтобы они правильно работали со строками или символьными массивами.

Это типичные конструкции, которые, возможно, придется изменить для поддержки нового типа UnicodeString.

Заключение

Вот и все потенциально узкие места в коде, которые нужно проверить на правильность для жизни в мире Юникода. Большая часть Вашего кода по-прежнему будет работоспособной. Большинство предупреждений, которые получит Ваш код от компилятора, можно легко исправить. Значительная часть моментов, которые нужно проверить, встречается достаточно редко, поэтому практически весь Ваш код будет работать просто прекрасно.

Илон Маск рекомендует:  Что такое код asp uncusername
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL