typedef-name обозначает тип, а не последовательность токенов (как это делает макрос). В вашем случае LPVOID
обозначает тип, также обозначаемый последовательностью токенов void *
. Таким образом, диаграмма выглядит как
// [...] is the type entity, which we cannot express directly.
LPVOID => [void *]
Семантически если указать тип const LPVOID
, вы получите следующую диаграмму (скобки вокруг спецификаторов означают «тип, обозначаемый спецификатором»):
// equivalent (think of "const [int]" and "[int] const"):
const LPVOID <=> LPVOID const => const [void *] <=> [void *] const
=> ["const qualified void-pointer"]
Это не то же самое, что последовательность токенов const void *
- потому что этот не будет обозначать тип указателя с константным квалификацией, а скорее указатель на тип с константным спецификацией (вещь, на которую указывает Const).
Синтаксически объявление параметров имеет следующую (упрощенную) форму:
declaration-specifiers declarator
Спецификаторы объявления в случае const void *p
равны const void
, поэтому базовый тип *p
является константным void
, но сам указатель не квалифицирован. Однако в случае const LPVOID p
спецификаторы объявления задают константное значение LPVOID
- это означает, что указывается сам тип указателя, что делает объявление параметра идентичным void *const p
.