Для чего нужен UINT?
Просветите меня, зубры программирования, для чего в стандартных заголовочных файлах, обеспечивающих вызов функций из API Windows, используется переопределение типов UINT и DWORD вместо unsigned int, CHAR вместо char и т. д. В чём смысл такой избыточности названий одних и тех же вещей? Особенно интересно, для чего нужны LPARAM и WPARAM, которые обычно всё равно приходится кастить в нужный тип, так что разница между ними в виде signed/unsigned практически никогда не используется.
Далее, очень часто в API используются 32битные переменные - HBRUSH, HWND, HPEN и т.д.. Чтобы их отличать и выполнять контроль типов при вызове функций и была введена такая избыточность. Зачем конкретно был введен CHAR - не знаю, наверное, до кучи.
Про UINT и DWORD. Первый - это целое число, а второй - четыре байта. В контексте 64 битных платформ разница должна быть понятна :) .
[QUOTE=tarekon]LPARAM есть typedef на LONG_PTR[/QUOTE]
- это в C++ Builder'e, а у меня в lcc LPARAM определён как long (заметьте, не long*), а WPARAM как unsigned int. Выходит, даже в разных компиляторах эти дополнительные типы определяются по-разному.
- это в C++ Builder'e, а у меня в lcc LPARAM определён как long (заметьте, не long*), а WPARAM как unsigned int. Выходит, даже в разных компиляторах эти дополнительные типы определяются по-разному.[/QUOTE]
И не только в C++ Builder'e, но и в MS VC++, и в Platform SDK. Думаю на то, что написано в lcc нужно смотреть скептически.
А почему UINT'ы создавались для Win95? Разве не для Win 3.х и иже с ними?
Появились-то они, может быть, и при Win16 (когда, действительно, использовались как 16-разрядные компьютеры, так и 32-разрядные), но фигурируют-то при описании функций для Win32.
А вообще, я всё это к тому, что, когда стал писать вместо всех этих HANDLE, HMODULE, HWND и прочее просто void*, вместо LPCSTR char* и т. д., программирование как-то упростилось. Может даже, за счет подсветки стандартных типов, а то UINT'ы и иже с ними теряются в тексте.
А вообще, я всё это к тому, что, когда стал писать вместо всех этих HANDLE, HMODULE, HWND и прочее просто void*, вместо LPCSTR char* и т. д., программирование как-то упростилось. Может даже, за счет подсветки стандартных типов, а то UINT'ы и иже с ними теряются в тексте.[/QUOTE]
Так набор функций со времен Windows 3.11 не сильно изменился... А вообще, использовать вместе HWND void* - ужасно! Пропадает всякая проверка типов, можно нечаянно в функцию, работающую с кистью, передать вместо кисти хэндл окна. Караул! Это же куча возможностей С++ по контролю ошибок вылетает в трубу! Нельзя так делать!
Кстати, для контроля типов можно использовать
#define STRICT
в самом начале программы. Тогда void* уже не напишешь ;)
А по-моему, если давать осмысленные названия переменным, ничего не перепутаешь. Например, пишу: void *hWnd, *hBrush, *hCursor - и всё понятно, где кисть, а где окно. А то когда в 1 функции что-то типа
HWND hWnd1, hWnd2;
HBRUSH hBrush;
HBITMAP hbmp1, hbmp2;
HCURSOR hcur;
HINSTANCE hinst;
HMODULE hm;
и ещё с десяток подобных вещей (утрирую, конечно), а по ходу работы нужно добавлять новые переменные, пока найдёшь куда вписать её объявление, "замучаешься" (чтоб не сказать грубо).
HWND hWnd1, hWnd2;
HBRUSH hBrush;
HBITMAP hbmp1, hbmp2;
HCURSOR hcur;
HINSTANCE hinst;
HMODULE hm;
и ещё с десяток подобных вещей (утрирую, конечно), а по ходу работы нужно добавлять новые переменные, пока найдёшь куда вписать её объявление, "замучаешься" (чтоб не сказать грубо).[/QUOTE]
Конечно, можно пользоваться любыми небезопасными приемами программирования и делать работающие программы. Но только вот непрофессионально это. Все равно что строить дома, не делая никаких предварительных расчетов - наобум. Маленькие домишки стояли и будут стоять, а вот стоэтажное здание уже не построишь. Так и тут - пока программка маленькая, все легко контролируется и пишется. А вот стоит развернутся, как появляются переменные с именем temp или i, по именам которых уже не поймешь, к какому типу они относятся. Написал одно выражение - работает, другое - работает, а в третьем ошибся и не заметил. Программа компилируется, но работает неверно (или почти верно, что еще хуже). А потом бегаешь по программе и ищешь, где же ты ошибся.
Или того хуже. Появилась новая 64 битная Windows, а в ней HMODULE стала 64 битным значением, а HBRUSH осталась 32 битной. И опять бегашь по коду, переправляешь void* на HBRUSH. А ведь можно было просто перекомпилировать код, если бы он был правильно написан...
Так на то это и временные переменные, что известны лишь в одной функции, так что их тип легко контролируется. Тем более, что в одной функции их много не бывает. А можно и временные переменные называть не temp, а, скажем, szTemp. A i сама за себя говорит - тип int.
[QUOTE=tarekon]Появилась новая 64 битная Windows, а в ней HMODULE стала 64 битным значением, а HBRUSH осталась 32 битной. И опять бегашь по коду, переправляешь void* на HBRUSH. А ведь можно было просто перекомпилировать код, если бы он был правильно написан...[/QUOTE]
- ну с какой это стати одни хэндлы станут 64-битными, а другие останутся 32-х?
Тем не менее, общая мысль мне ясна. Именно это я и ожидал услышать. Жаль только, что никто больше не заинтересовался обсуждаемой темой.
Если коротко, для поддержки совместимости и переносимости кода.
Насчет CHAR. У многих WinAPI-функций есть A и W варианты - первый в ANSI кодировке, другой UNICODE. Например, функция CreateWindow - это на самом деле макрос, раскрывающийся в зависимости от настроек проекта в CreateWindowA или CreateWindowW. Так вот. Возможно, я ошибаюсь, но скорее всего CHAR - также макрос, который раскрывается либо в char, либо в wchar_t в зависимости от применяемой кодировки. Это для поддержки переносимости кода с ANSI версии на UNICODE и обратно (достаточно просто поменять свойства проекта и перекомпилировать).
В MS VC 2005 есть всплывающая подсветка макросов. Когда наводишь мышь, видно, на что он раскрывается.
Насчет CHAR. У многих WinAPI-функций есть A и W варианты - первый в ANSI кодировке, другой UNICODE. Например, функция CreateWindow - это на самом деле макрос, раскрывающийся в зависимости от настроек проекта в CreateWindowA или CreateWindowW. Так вот. Возможно, я ошибаюсь, но скорее всего CHAR - также макрос, который раскрывается либо в char, либо в wchar_t в зависимости от применяемой кодировки. Это для поддержки переносимости кода с ANSI версии на UNICODE и обратно (достаточно просто поменять свойства проекта и перекомпилировать).[/QUOTE]
Немного промахнулся. Таким макросом является TCHAR. CHAR же есть typedef на char
- ну с какой это стати одни хэндлы станут 64-битными, а другие останутся 32-х?
Тем не менее, общая мысль мне ясна. Именно это я и ожидал услышать. Жаль только, что никто больше не заинтересовался обсуждаемой темой.[/QUOTE]
Дело в разном физическом смысле этих хендлов. HMODULE это адрес начала модуля в памяти, на 64 битных машинах он ДОЛЖЕН быть 64 битным. HBRUSH - это индекс в таблице кистей, а размер этой таблицы совсем не обязательно должен зависеть от разрядности процессора. И скорее всего, не будет.