#c #pointers #typedef
#c #указатели #typedef
Вопрос:
Итак, обычно мы вводим typedef для другого типа или указателя на функцию, но typedef тип для указателя мне кажется странным. Например, в winnt.h мы получили:
typedef void *HANDLE;
typedef PVOID HANDLE;
и PVOID является:
typedef void *PVOID,*LPVOID;
Согласно этому, в первом операторе это должно быть *HANDLE, потому что это указатель на void , в то время как PVOID уже является указателем на void , поэтому его не нужно объявлять как указатель.
Однако, в чем преимущество typedef тип для указателя? Разве это не более запутанно?
Ответ №1:
в чем преимущество typedef тип для указателя? Разве это не более запутанно?
Обычно модулям / библиотекам необходимо поддерживать некоторое внутреннее состояние для их правильного функционирования. Это внутреннее состояние должно быть прочитано / проверено в каждом api, который вызывается для этого модуля / библиотеки. Таким образом, пользователь модуля должен передавать эту информацию каждому API, который они вызывают. Но разработчик библиотеки не хочет, чтобы пользователи библиотеки могли видеть содержимое этого поддерживаемого состояния, потому что, если им это разрешено, кто-то может сыграть злую шутку или честно изменить состояние, и результаты этого могут быть катастрофическими для модуля. Чтобы избежать такого сценария, модули маскируют свои переменные, поддерживающие состояние, как a void*
, так что теперь оно непрозрачно (его содержимое не видно) для пользователей модуля. Для удобства, позволяющего пользователям не путаться в использовании void *
, они обычно void *
вводят значение as HANDLE
, это делается для простоты использования клиентами модуля / библиотеки.
Что касается упомянутого кода:
typedef void *PVOID,*LPVOID;
означает, что отныне, где бы вы ни упоминали PVOID
, он будет обрабатываться как void *
тип.
Итак, в,
typedef PVOID HANDLE;
эквивалентно:
typedef void *HANDLE;
Потому PVOID
что это не что иное void *
, как .
Комментарии:
1. Я не вижу преимущества этого перед прямым объявлением непрозрачной структуры, подобной этой
class HANDLE;
. Это немного лучше предотвратило бы случайное упущение. Или я что-то упускаю?2. А что с C API, например? 😉
3. Итак, ДЕСКРИПТОР typedef void* совпадает с ДЕСКРИПТОРОМ typedef void * ? Ну, я знаю об этом, но для меня это странно.
4. @MichaelAnderson: В ответе говорится, почему это делается, в нем не говорится, что это так, как это должно быть сделано. Это традиционный способ C сделать это. И устаревшие коды все еще иногда используют его таким же образом. Я бы согласился с тем, что прямое объявление класса — лучший способ, но это не всегда то, что делают устаревшие процедурные промежуточные программы / приложения c . Да, существуют процедурные промежуточные программы C , и это мрачная, но реальность.
5. @MichaelAnderson: A
HANDLE
может указывать на довольно много разных структур. Он используется практически для всего в WIN32 (и WIN16, из которого он исходит) API.
Ответ №2:
И если вам интересно, зачем использовать 2 typedef для одного и того же значения, ответ таков: они имеют разное значение и варианты использования. HANDLE — это дескриптор объекта, а PVOID — это просто указатель на любой тип. Так что это просто для лучшей читаемости.
Ответ №3:
говоря по-английски,
typedef void *PVOID
означает использование void * вместо PVOID . amp;
typedef PVOID HANDLE;
означает использование PVOID вместо ДЕСКРИПТОРА amp; из-за нашего предыдущего typedef это дополнительно означает
использование void * вместо ДЕСКРИПТОРА
это для лучшей читаемости кода.