Некий BV надоумил меня нарисовать пару картинок на тему устройства типов данных.
Строки
Тут я описал три способа хранить строки(на самом деле способов можно придумать бесчисленное множество, но наиболее распространены как мне кажеться эти).
Итак, первый тип, BSTR(именно он использовуется в переменных типа String в VB6) - строка из unicode-символов, которая кончается двухбайтовым терминатором и перед которой стоит ее длина. Ввиду того, что сама строка содержит свою длину она может содержать произвольные символы.
Во второй тип, ABSTR, VB преобразует строки перед тем как передать их в API-функции. Этот тип отличается от BSTR тем, что содержит однобайтовые символы, вместо двухбайтовых.
Третий, LPSTR традиционно используется в C. Этот тип нигде не хранит длину строки, окончание строки определяется по нулевому терминатору в конце. Строка содержит однобайтовые символы. В отличие от первых двух типов, где нулевой терминатор стоит в конце лишь для совместимости со старыми типами, в LPSTR нулевой терминатор необходим, так как он указывает на конец строки. Так же нелишне отметить, что LPSTR строки по определению не могут содержать нулевых символов. Если вы поместите в LPSTR нулевой символ то для всех использующих ее функций строка "обрежется" до этого символа(по вполне очевидным причинам). Не менее важный минус LPSTR заключается в том, что время определения длины такой строки прямо пропорционально длине строки. Для очень длинных строк, порядка мегабайта, определение длины может оказаться весьма дорогой ситуацией. Типы (A)BSTR этого недостатка лишены.
Адреса
Напоследок раскажу об устройстве адреса в ОС windows. Вам ведь известно, что любую ячейку памяти процесса можно "обозвать" четырехбайтовым числом? Если известно, то увы вы малость заблуждаетесь.
На самом деле АП процесса содержит как минимум два сегмента - основной сегмент и вспомогательный.
Номер основного сегмента хранится в регистрах ds,cs,ss,es. gs не используется.
В fs хранится номер второго, служебного сегмента(который правда, является частью основного сегмента) и в этом сегменте храняться некоторые полезные данные о процессе, например его id.
Однако на практике этот сегмент используется только внутри ОС, так как его содержимое вообще говоря малокументировано(описание некоторого содержимого fs можно прочитать в топике tyomitch).
А вот со вторым сегментом, номер которого всегда хранится в DS и ведет работа наша программа.
Если теперь принять утверждение о том, что написанная нами часть кода программы будет работать только с теми данными, что лежат в основном сегменте, то становится очевидным, почему так часто говорят что адрес в windows это только лишь четырех байтовое число.
Полное устройство адреса показано на рисунке, как видно он состоит из трех частей, номера сегмента, номера страницы и смещения внутри страницы.
Номер сегмента, как было сказано всегде лежит в ds и ss, так что про него можно "забыть" в большинстве случаев.
Номер страницы и смещение храняться внути 4-х байтового числа, void* в C++ или просто Long в VB. При этом под смещение страницы выделяется 12 бит а под номер - 20 бит. Если вам вдруг потребуется разрубить адрес на две части(я с трудом, правда, представляю, зачем вам это), то можно воспользоваться такой простой формулой:
- Код: Выделить всё
Offset=Address\&h1000
PageNumber=Address AND &hfffff000