Более конкретно, почему во многих случаях одна и та же вещь typedef имеет несколько разных имен, и почему typedef типы указателей (иногда затеняя логику)?
typedef
Например:
typedef const WCHAR *LPCWSTR, *PCWSTR;
Какой смысл в этом?
Здесь на самом деле происходит несколько разных вещей:
Первые указатели ближнего / дальнего хода: еще в Win16 дней у вас были ближние и дальние указатели;ближние указатели были в основном только 16-битными смещениями, поэтому могли ссылаться только на объекты в пределах 64 КБ от указателя данных приложения по умолчанию (DS или регистр сегмента данных), но они были небольшими и быстрыми;в то время как больший «дальний указатель» или длинный указатель состоят как из сегмента, так и из смещения, поэтому он может ссылаться на что-либо в пределах адресного пространства 1М.Когда появился 386, весь этот сегмент: офсетный бизнес, наконец, ушел, и все указатели были просто 32-битными адресами в плоские 32-битные адресные пространства.И именно поэтому есть версии P ... и LP ...
Зачем вообще беспокоиться о typedefs?Это просто удобство или сокращение: набирать «LPSTR» удобнее, чем «const char far *».Но это также становится узнаваемой идиомой: вы видите LPSTR и сразу понимаете, что именно так Windows работает со строками в своем API.
Здесь также происходит абстракция: Windows обычно определяет еесобственные версии типов и использует их вместо версий C.Таким образом, API-интерфейсы Windows используют DWORD вместо int или VOID вместо void.Это было необходимо для того, чтобы закрыть некоторые дыры в C в то время - bool не было, поэтому введение BOOL позволило избежать использования разными API-интерфейсами разных типов для представления логических значений (например, char vs int).Это также в некоторой степени сделало Windows API независимым от базовой реализации C: C не требует, чтобы int был определенного размера: это может быть 16 или 32 бита в зависимости от компилятора.Но для OS API важно точно указать эти вещи.Поэтому вместо использования int или long в Windows вместо этого используются INT и LONG, которые затем определяются по мере необходимости, и typedefs для любого базового типа C выполняет реальную работу.
Наконец, некоторые изэти определения типов на самом деле намекают на конкретные случаи использования помимо информации о типах.BOOL и INT оба являются typedef'd как int, но ясно, что параметр API, указанный как BOOL, будет использоваться в смысле TRUE / FALSE, а не как целочисленное значение.(Помните, что это предшествует типу 'bool'.) Аналогично, BYTE - беззнаковый символ - предполагает, что параметр будет использоваться как 8-разрядное числовое значение, а не как буквенно-цифровой или символьный символ.И LPSTR указывает, что значение, как ожидается, будет строкой с нулевым символом в конце, а не просто указывает на произвольные значения символов.BSTR и LPWSTR имеют одинаковый базовый typedef - оба они WCHAR * - но BSTR имеют префикс длины и поэтому должны быть выделены с помощью API-интерфейса SysAllocString, так как наличие отдельного typedef здесь помогает разделить эти требования в коде и документе:вы видите API, который принимает BSTR в качестве параметра, затем вы знаете, что вы не можете просто передать широкую строку, даже если базовый тип такой же, есть дополнительные требования для этого параметра.
Причина, по которой есть и PCWSTR, и LPCWSTR, заключается в том, что в древние времена существовала разница. LPCWSTR раньше был постоянным WCHAR FAR *.
Я полагаю, что одна из основных целей этого проекта - позволить типам функций служить документацией их назначения и ожидаемых форматов данных.