Tamaño de tiempo de comstackción condicional

Quiero definir una macro si una condición que involucra sizeof es verdadera y no hacer nada (pero aún así comstackr) si es falsa. Si el preprocesador admite sizeof , se vería así:

 #if (sizeof(void*) <= sizeof(unsigned int)) // what goes here? # define POINTER_FITS_INTO_UINT #endif 

Hay algunas páginas (p. Ej., Http://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ ) que explican cómo realizar una aserción en tiempo de comstackción en sizeof (y no comstackr si falla), pero no veo una manera de extender este enfoque a lo que quiero.

Simplemente no puedes hacerlo. sizeof es un operador de tiempo de comstackción. #if y #define y relacionados con preprocesador. Como el preprocesador se ejecuta ANTES del comstackdor, esto simplemente no funcionará. Sin embargo, es posible que pueda encontrar un conmutador de comstackción arcano que le permita realizar varias pasadas (es decir, preprocesar, simular comstackción, preprocesar, comstackr) pero, para ser justos, dejaría de intentar hacer lo que desea. No está destinado a funcionar y, simplemente, no funciona.

Lo mejor que puedes hacer es establecer tales definiciones como comandos -D pasados ​​al comstackdor. Puede afirmar estáticamente que los elegidos son correctos. De esta manera, solo tiene que configurar algunas definiciones externamente para un modo de comstackción dado (por ejemplo, PowerPC Release) y así sucesivamente.

La solución correcta para su problema es usar los encabezados estándar C99:

 #include  #include  

Solo necesita uno de los dos porque #include incluye el material de #include ; sin embargo, gran parte del material en solo es relevante para E / S formateadas con scanf() e printf() .

Dada la condición putativa:

 #if (sizeof(void*) <= sizeof(unsigned int)) // what goes here? # define POINTER_FITS_INTO_UINT #endif 

Lo que parece ser después se conoce como:

 uintptr_t 

Ese es el tipo entero sin signo que es lo suficientemente grande como para contener cualquier puntero (es decir, cualquier puntero de datos en el estándar C; POSIX impone una regla adicional de que también debe ser lo suficientemente grande como para contener los punteros de función). El tipo uintptr_t se define en .

Si posteriormente va a imprimir dichos valores, o punteros en bruto, puede utilizar la información de :

 printf("Pointer = 0x%" PRIXPTR "\n", uintptr_value); printf("Pointer = 0x%" PRIXPTR "\n", (uintptr_t)any_pointer); 

Esto describe cómo falsear aserciones en tiempo de comstackción en C. La versión corta es para usar sentencias de conmutación:

 #define COMPILE_TIME_ASSERT(pred) \ switch(0){case 0:case pred:;} 

Si pred evalúa como 0, como hace una expresión booleana falsa en C, el comstackdor arrojará un error.

Suponiendo que C99, podría utilizar

 #include  #include  #if UINTPTR_MAX <= UINT_MAX ... 

lo que implica sizeof (void *) <= sizeof (intptr_t) <= sizeof (int) en cualquier implementación sana del lenguaje C.

Aunque la pregunta está etiquetada como C en lugar de C ++, puede resultarle útil saber que C ++ 0x define un mecanismo para las aserciones estáticas que el comstackdor comprueba, no el preprocesador.

El ejemplo de Wikipedia es particularmente relevante:

 static_assert (sizeof(int) <= sizeof(T), "T is not big enough!") 

Dado que las otras respuestas ya explicaron por qué sizof no se puede usar con #if , permítame ofrecerle una solución simple para su caso (sorprendentemente aún no se ha mencionado). Echa un vistazo a

https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros .

Menciona varias macros __SIZEOF_XYZ__ predefinidas que realmente pueden usarse en la fase de preprocesamiento, es decir, también en #if . Suponiendo que unsigned int y unsigned int son del mismo tamaño, su ejemplo se puede hacer así:

 #if __SIZEOF_POINTER__ == __SIZEOF_INT__ #define POINTER_FITS_INTO_UINT #endif 

Editar

No importa, como señaló Steve Rowe, estos valores del preprocesador también se configuran por sizeof por lo que acabamos de completar el círculo.

Dado que sizeof no evalúa hasta el momento de la comstackción, debe confiar en otros valores de preprocesador. Así es como lo haría:

 #include  #if PTRBITS <= INTBITS # define POINTER_FITS_INTO_UINT #endif 

Estás confundiendo dos pasos de comstackción aquí. Cuando comstack un progtwig en C, el primer paso es el preprocesador que resuelve las macros y cualquier línea que comience por ‘#’. Luego viene la comstackción que incidentalmente evalúa el tamaño de las expresiones.

Estos son dos binarios diferentes y no puede pasar ese tipo de información de uno a otro. Tendrá que usar macros definidas por el sistema, como __i386__ o __x86_64__, si desea calcular en qué architecture se encuentra y luego deducir los tamaños int y de puntero.

Una forma de entender esto es el concepto de modelo de datos (ver, por ejemplo, http://sourceforge.net/p/predef/wiki/DataModels/ ).

Hay varios modelos de datos que incluyen LP32 ILP32 LP64 LLP64 ILP64 y en la mayoría de las plataformas, el comando cc frontend define el modelo actual (por ejemplo, _ILP32 significa int, long y puntero son 32 bits, mientras que _LP64 significa largo y puntero son 64bit).