вторник, 30 ноября 2010 г.

Путаница в параметрах №2

Это перевод Parameter confusion #2. Автор: Майкл Каплан.

Кажется, прошли годы с того момента, когда я говорил про путаницу в параметрах функции LCMapString при создании ключей сортировки.

Ох, постойте-ка, это было только вчера :-)

Существует и другое направление для возникновения путаницы - в этот раз не из-за отличий, а наоборот, из-за постоянности.

Давайте посмотрим на функцию GetLocaleInfo. Её прототип достаточно прост:
function GetLocaleInfo(
  Locale: LCID;      // идентификатор локали
  LCType: LCTYPE;    // тип информации
  lpLCData: LPTSTR;  // буфер для информации
  cchData: Integer;  // размер буфера
): Integer; stdcall;
Достаточно просто, да? Этот cchData подчиняется набору правил:
cchData
[in] Указывает размер буфера lpLCData в символах. Если cchData равно нулю, то функция возвращает число символов, необходимых для хранения информации, включая терминатор, а буфер, указанный в lpLCData не используется.
Ну, не совсем просто. Поскольку вы передаёте строку, то вы просто измеряете её размер в символах, вместо байт.

Конечно же, когда вы указываете флаг LOCALE_RETURN_NUMBER в параметре LCType, всё становится более сложным:
LOCALE_RETURN_NUMBER
Windows 98/Me, Windows NT 4.0 и выше: функция возвращает значение как число, вместо строки. Буфер, который получает значение, должен иметь размер DWORD. Этот флаг может быть скомбинирован с любым спецификатором, начинающимся с LOCALE_I.
Ой, это всё равно что запустить кошку в голубятню. Что же теперь надо передавать в параметр cchData, если размер буфера должен быть 4 байта?

Ответ обманчиво прост - это должно быть то же значение, но выраженное в символах. Проще всего сделать это - передать SizeOf(DWORD) div SizeOf(Char).

Вы можете задуматься в случаях, когда число представлено другим типом - вроде LOCALE_ICALENDARTYPE (который возвращает CALID). Но если вы посмотрите на объявление CALID в winnls.h, то вы увидите, почему я не беспокоюсь о передаче SizeOf(CALID) div SizeOf(Char) специально для этого случая:
//
//  Calendar ID.
//
type
  CALID = DWORD;
OK, возможно, в итоге это покажется вам простым после этого объяснения. Много людей находят это поведение запутывающим...

This post brought to you by "ޝ" (U+079d, a.k.a. THAANA LETTER SHEENU)

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.