Poniższy kod pochodzi z istniejącej aplikacji, która musi zostać skompilowana zarówno w C jak i C++. Jest makro:Proszę wyjaśnić to ostre makro, które wykonuje odlewanie i sprawdzanie typu:
/* Type-checking macro to provide arguments for CoCreateInstance() etc.
* The pointer arithmetic is a compile-time pointer type check that 'obj'
* really is a 'type **', but is intended to have no effect at runtime. */
#define COMPTR(type, obj) &IID_##type, \
(void **)(void *)((obj) + (sizeof((obj)-(type **)(obj))) \
- (sizeof((obj)-(type **)(obj))))
, który jest używany w następujący sposób:
ISomeInterface *object;
CoCreateInstance(&CLSID_SomeInterfaceImpl, NULL,
CLSCTX_INPROC_SERVER, COMPTR(ISomeInterface, &object))));
tu chodzi o to, że dwa ostatnie parametry CoCreateInstance()
są IID&
i void**
i chwyta makro ISomeInterface**
i konwertuje go do IID&
i void**
w tym samym czasie wymuszenie sprawdzania podczas kompilacji, czy adres przekazany w miejsce ISomeInterface**
jest rzeczywiście adresem zmiennej wskaźnika ISomeInterface*
.
Ok, ale co potrzeba
((obj) + (sizeof((obj)-(type **)(obj))) \
- (sizeof((obj)-(type **)(obj)))
złożonego wyrażenia? Widzę, że sprawdzanie typu jest wymuszane podwyrażeniem (obj)-(type**)(obj)
. Jaka jest potrzeba dodania, a następnie odjęcia sizeof()
? A jaka jest potrzeba rzutowania na void*
przed rzutowaniem na void**
?
Przypuszczam, że to samo można zrobić w następujący sposób:
#define COMPTR(type, obj) &IID_##type, \
(void **)(sizeof((obj)-(type**)(obj)), obj)
tutaj pierwsza część operatora przecinkami zawierałby sizeof()
które egzekwowania typecheck i oceny do stałej, druga część będzie tylko wytworzeniem ten sam wskaźnik i wskaźnik będą rzutować na void**
.
Co oryginalne makro może zrobić zgodnie z sugestią tego, co sugeruję? Jaka jest potrzeba tych komplikacji?
I dlatego jest to zły kod. Niech zgadnę, zmagałeś się z tym przez cały dzień? – orlp
@noccracker: Nie, nie utrzymuję tego kodu, właśnie go znalazłem i byłem ciekawy jak to działa. – sharptooth
+1 dla hardcore w tytule, powinien być tagiem! –