Когда заголовочные файлы Windows API были впервые созданы 25 лет назад, int
составлял 16 бит, а long
составлял 32 бита. Заголовочные файлы со временем эволюционировали, отражая изменения в компиляторах и оборудовании.
Кроме того, Microsoft C ++ не единственный компилятор C ++, который работает с заголовочными файлами Windows. Когда Microsoft добавила ключевое слово size_t
, не все компиляторы поддержали его. Но они могли бы легко создать макрос, SIZE_T
, чтобы выразить его.
Кроме того, существуют (или были) автоматизированные инструменты, которые преобразуют файлы заголовков API из C / C ++ в другие языки. Многие из этих инструментов изначально были написаны для работы с текущими (на тот момент) определениями заголовков. Если бы Microsoft просто изменила заголовочные файлы, чтобы упростить их, как вы предлагаете, многие из этих инструментов перестали бы работать.
По сути, файлы заголовков сопоставляют типы Windows с наименьшим общим знаменателем, чтобы с ними могли работать несколько инструментов. Временами кажется, что это что-то вроде беспорядка, и я подозреваю, что если Microsoft захочет отбросить какое-либо подобие обратной совместимости, они могут уменьшить большую часть беспорядка. Но это сломало бы много инструментов (не говоря уже о большом количестве документации).
Так что, да, заголовочные файлы Windows иногда бывают беспорядочными. Это цена, которую мы платим за эволюцию, обратную совместимость и возможность работать с несколькими языками.
Дополнительная информация:
Я согласен, что на первый взгляд все эти определения кажутся сумасшедшими. Но как тот, кто видел, как заголовочные файлы Windows эволюционировали со временем, я понимаю, как они возникли. Большинство этих определений имело смысл, когда они были представлены, даже если сейчас они выглядят сумасшедшими. Что касается конкретного случая ULONGLONG
и DWORD64
, я предполагаю, что они были добавлены для согласованности, поскольку старые заголовочные файлы имели ULONG
и DWORD
, поэтому программисты ожидали двух других. Что касается того, почему ULONG
и DWORD
были определены, когда они являются одним и тем же, я могу представить несколько возможностей, две из которых:
- Одна команда API использовала
ULONG
, а другая - DWORD
, и когда заголовочные файлы были объединены, они просто сохраняли оба, а не ломали код путем преобразования в один или другой.
- Некоторым программистам удобнее думать с точки зрения
ULONG
, чем DWORD
. ULONG
подразумевает целочисленный тип, с которым вы можете выполнять математику, тогда как DWORD
просто подразумевает общее 32-битное значение некоторого вида, обычно это ключ, дескриптор или другое значение, которое вы не хотите изменять .
Ваш первоначальный вопрос состоял в том, были ли какие-то рассуждения за, казалось бы, безумными определениями, или есть абстракция, которую вы не пропустили. Простой ответ заключается в том, что определения развивались, а изменения имели смысл в то время. Особой абстракции не существует, хотя намерение состоит в том, что если вы напишите свой код для использования типов, определенных в заголовках, то вы должны иметь возможность переносить ваш код с 32-разрядного на 64-разрядный без беда. То есть DWORD
будет одинаковым в обеих средах. Но если вы используете DWORD
для возвращаемого значения, когда API говорит, что возвращаемое значение равно HANDLE
, у вас будут проблемы.