2012-09-23 36 views
5

He estado revisando y refacturando algunos códigos. Terminé cambiando en función de:Incoherencia cercana y lejana

void setPerspective(float nearP = 0.1f, float farP = 1000.0f); 

a

void setPerspective(float near = 0.1f, float far = 1000.0f); 

y empecé a recibir una gran cantidad de extrañas 'missing ;' y 'missing)' errores.

Parece que near y far son #define d en windef.h. Lo suficientemente justo; Evitaré usarlos.

Pero entonces me di cuenta en otro archivo de cabecera:

void setPerspective(float fov, float aspect, float near, float far); 

Sin embargo, me sale ningún problema. Ambos archivos de encabezado tienen el mismo #include s ...

¿Alguna idea de por qué tengo problemas en uno, pero no en otro? No parece ser los parámetros predeterminados. ¿Es una ordenación arbitraria de #include s la que podría estar causando problemas con un archivo de encabezado y no con otro?

+0

O quizás el encabezado define o no define 'near' y' far' dependiendo de alguna condición. –

Respuesta

7

Las fichas near y far probablemente se definen a ser nula en un vacío #define como esto

#define near 
#define far 

por lo que el pre-procesador reemplazará con nula - desaparecen antes del compilador de procesamiento de la fuente.

La primera declaración de la función incluye la asignación por defecto para los parámetros

void setPerspective(float nearP = 0.1f, float farP = 1000.0f); 

El compilador interpreta correctamente nearP y Farp como el nombre del parámetro y float como el tipo. Cuando se cambia a nearPnear y farP-far el pre-procesador de los reemplaza por nula y tiene una asignación para el tipo float ... y el compilador le da un ataque ... esto es lo que ve el compilador:

void setPerspective(float = 0.1f, float = 1000.0f); 

en la segunda cabecera presentar los parámetros en el prototipo de función no tienen asignación por defecto, y el compilador ve los parámetros son flotador y no ve near y far porque son nulos ... así que en vez de este

void setPerspective(float fov, float aspect, float near, float far); 

el compilador ve esto

void setPerspective(float fov, float aspect, float , float); 

que es un prototipo de función perfectamente legal (no es suficiente con dar los parámetros de nombres).

+0

Esto es lo que '# undef' es para;) – slugonamission

+0

@slugonamission - sí, tiene razón, lo he agregado a mi respuesta, ¡gracias! – amdn

+0

@slugonamission - después de pensarlo, me di cuenta de que solo un '# define' vacío reemplazaría' far' y 'near' con null ...' # undef' le dice al preprocesador que el símbolo ya no está definido, por lo que representa sí mismo. – amdn

2

mirada a este post: Near and Far pointers

parece que han sido tipos de punteros para acceder a diferentes tipos de memoria, pero ya no se usan.

Parece que hay una razón para que se llamen nearP y farP. :)

+0

o 'znear' y' zfar'. Es realmente molesto, tbh. –

4

Supongo que está compilando en una máquina con Windows.

Hace mucho tiempo, perdido en las brumas del tiempo, había máquinas como las Intel 8086, 80186 y 80286. En estas máquinas, tenías memoria limitada disponible. En su mayoría usaban punteros de 16 bits. Pero luego los programas crecieron un poco, por lo que las palabras clave near y far se agregaron como calificadores para identificar diferentes tamaños de puntero.

Lo que te encuentras es un remanente de esos oscuros días primordiales. Las computadoras sanas (80386 en adelante) no necesitaban la notación near y far, pero los compiladores continuaron apoyándolas por compatibilidad con versiones anteriores.

Si esta diagnosis es precisa, evite usar los nombres near y far; trátelos como palabras clave sobrantes de una versión anterior del idioma.

+0

No hay excusa para que los archivos de encabezado del sistema entren en el espacio de nombre de usuario de esta manera; es un diseño de archivo de encabezado descuidado. – Kaz

+3

La excusa es que las decisiones se tomaron hace 20 o 30 años, antes de que se hubieran enunciado las reglas de contaminación del espacio de nombres, y la compatibilidad con versiones anteriores se ocupa del resto. No me gusta; pero esa es la forma en que Microsoft ha trabajado desde siempre. –

+0

@Kaz: Es fácil criticar, pero muchas veces no hay una respuesta "correcta". La elección fue enviar un encabezado subóptimo o romper aplicaciones existentes. Hicieron la elección correcta –

2

Los archivos de encabezado están influenciados no solo por sus propios #include s sino también por los #include s que se encuentran en el archivo de origen antes de esos encabezados.

/* foo.cpp */ 
#include "bar.h" 
#include "foo.h" // foo.h is influenced by whatever is brought in by bar.h 

Los identificadores far y near (así como otros) son extensiones se encuentran en algunos compiladores y dirigidos al 8086/88 arquitectura segmentada (en la que corrían MS-DOS y Windows 3.x). Puede haber algo en los archivos de encabezado de Windows para soportar el código heredado, como quizás #define far (defínalo en nada).

En una nota diferente, generalmente debe utilizar double para números de coma flotante. El tipo float es para guardar el almacenamiento en matrices grandes (puede o no ser menor que double). En las plataformas que tienen números de coma flotante IEEE 754, float suele ser un número de 32 bits: tiene una mantisa de 7 bits exponsent y 24 bit, que es bastante pobre. Mientras que double es un tipo de 64 bits, con un exponente de 11 bits y una mantisa de 52 bits: rango y precisión sustancialmente mejores.

+0

Diría que el renderizado predeterminado del flotador es más corto, lo que a veces es deseable –

Cuestiones relacionadas