Почему MAKEINTRESOURCE () работает? - PullRequest
       5

Почему MAKEINTRESOURCE () работает?

17 голосов
/ 31 августа 2010

Макрос определяется как:

#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))

Почему это может быть использовано для указания либо идентификатора ресурса (16-разрядного целого без знака), либо его имени (указатель на массив символов)?Разве это эффективно не ограничивает адресное пространство (в 32-разрядной системе) 16-разрядным?Иначе как система узнает, использую ли я идентификатор или имя?

Ответы [ 3 ]

21 голосов
/ 31 августа 2010

Это работает, потому что Windows не позволяет отображать страницы для первых 64 КБ адресного пространства.Поймать ссылки на нулевой указатель.Но я думаю также, чтобы ловить ошибки указателя в программах, которые были преобразованы из 16-разрядной версии Windows.

Побочным эффектом является то, что это позволяет надежно различать идентификаторы ресурсов, упакованные в значение указателя, поскольку они будутвсегда указывать на не отображаемую память.

17 голосов
/ 31 августа 2010

Макрос MAKEINTRESOURCE просто выполняет приведение между числовым параметром и указателем строки.Полученный указатель строки недействителен и не может быть разыменован как имя ресурса.Однако API обработки ресурсов обнаруживает такие указатели по их абсолютному значению и обрабатывает их как идентификатор ресурса, а не имя ресурса.Поскольку API в стиле C не поддерживает перегрузку, они не могут определять две функции, такие как:

HICON LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName);
HICON LoadIcon(HINSTANCE hInstance,UINT resourceId);

Поэтому разработчики API решили использовать одну и ту же функцию для обоих случаев, предоставляя макрос MAKEINTRESOURCE для пользователей API.Я считаю, что две разные функции могут выглядеть лучше:

HICON LoadIconByName(HINSTANCE hInstance,LPCTSTR lpIconName);
HICON LoadIconById(HINSTANCE hInstance,UINT resourceId);

Но это не тот способ, которым реализован Windows API.Допустимый идентификатор ресурса всегда меньше минимально возможного значения указателя.Параметр имени ресурса передается в API без этого макроса, и его значение не ограничено.

4 голосов
/ 31 августа 2010

Да, это ограничивает адресное пространство, но не так сильно, как вы думаете.Они эффективно вырезали 64 КБ из вашего 4 ГБ адресного пространства.Большая часть, если не вся, этих 64 КБ уже зарезервирована для других задач в Windows, поэтому эффективная потеря - ничто.

В целом, это экономия места, поскольку им не требуется дополнительная информация дляразличать указатель и целочисленный идентификатор.Это было изобретено еще в старые добрые времена, когда пространство было на высоте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...