2010-11-21 12 views
7

¿Cuál es el propósito de los tipos específicos de API tipo GLsizei GLint GLvoid?¿Cuál es el propósito de los tipos específicos de API tipo GLsizei GLint GLvoid?

Veo esto en todas partes en el código c y C++. Los tipos básicos a menudo se tipifican con el prefijo/sufijo de las bibliotecas. ¿Cuál es el razonamiento detrás de esto? ¿Es esta una buena práctica? ¿Deberían mis programas estar haciendo algo similar?

A primera vista, parece que el código es un poco menos legible. Tienes que tomar un instante para traducir GLint a int en tu cabeza, y ese es un ejemplo fácil.

Algo como UINT hace más porque para mí, al menos esto está acortando el int sin signo en cuatro letras.

Respuesta

3

No se trata de abreviar los nombres, sino acerca de la portabilidad. Las diferentes plataformas necesitarán escribir esas cosas de manera diferente.

En Std-C, long puede ser de 32 o 64 bits, dependiendo de su compilador/destino, por lo que no se puede suponer con seguridad que tiene un tamaño determinado. Un autor de la biblioteca escribirá así su propio tipo, garantizando un cierto tamaño, con el conocimiento de la plataforma objetivo.

E.g.

#ifdef _WIN32 
typedef __int64 INT64; // long will not be 64 bit on Windows/VC. 
#elif __GNU_C__ 
typedef long INT64; // gcc typically uses 64 bit longs. 
#elif // ... other platforms ... 
... 
#endif 

Y si compiladores cambiar las propiedades de tipo en versiones futuras, los tipos se pueden editar en un solo lugar.

En el pasado también tuvo un caso típico en el int podría ser de 16 o 32 bits de tamaño, por lo que no podría simplemente utilizar el crudo tipo int de código en el que necesitaba un argumento -sized DWORD.

De ahí que tenga cosas como LPARAM y WPARAM.

También se utiliza como una forma de abstracción. Es por ello que se ve typedefs como

typedef int Handle; 

Porque si bien se trata de una int ahora, el autor de la biblioteca se reserva la posibilidad de cambiar más adelante por la pista a cualquier otra cosa, por ejemplo un void *, o de cualquier otro tipo que consideren necesarias.

Pero el código del cliente no necesita saber específicamente que es int, ya que es lo que actualmente es. Todo lo que el cliente necesita saber es pasarlo a las funciones que aceptan un tipo Handle.

Typedefs también permiten la configuración en tiempo de compilación. P.ej. algunas bibliotecas pueden tener un tipo Real para números reales. Se podría definir de una manera como

#ifdef USE_DOUBLE_PREC 
typedef double Real; 
#else 
typedef float Real; 
#endif 

Y el usuario de la biblioteca se puede configurar opcionalmente /DUSE_DOUBLE_PREC al compilar para conseguir el apoyo de doble precisión flotador, pero lo importante es que ningún código de la biblioteca tiene que cambiar para que esto trabajo, ya que ha sido abstraído.

1

Da la capacidad de cambiar el typedef en un lugar en lugar de buscar y reemplazar en toda la base de código si surgiera la necesidad de cambiar el tipo subyacente. Sin embargo, también lo encuentro más "ruidoso" que cualquier cosa y rara vez lo he visto alguna vez en un escenario de la vida real.

El único ejemplo que he visto un uso decente es para flotadores si trabajas en juegos y es posible que necesites tener tu juego portado desde/hacia la Nintendo DS ya que el DS funciona de forma nativa con números de punto fijo . En ese caso, tiene un typedef especial para el float, por lo que realmente se typedef'ed a un float en la mayoría de las plataformas y a una clase especial de punto fijo en el DS.

+0

El punto fijo y el flotador tienen tan poco en común que cualquier código que funcione con punto fijo probablemente desee y debería usar punto fijo en todas partes ... –

+0

Se sorprenderá de lo fácil que es abstraer eso en una clase. Una empresa para la que contraté trabajo tenía un motor que tenía BLAH_FLOAT (donde "BLAH" eran las iniciales de su empresa) en todas partes, por lo que las versiones de código DS y no DS coexistían pacíficamente. –

+0

No quise decir en implementación sino en semántica. Por ejemplo, si sus valores son coordenadas, deben ser punto fijo o punto flotante con un sesgo ** enorme ** agregado. De lo contrario, la precisión varía según la posición, ya que es mucho más alta en el origen que muy alejada de ella, lo que significa que el comportamiento no es invariable por la traducción. –

2

En su mayor parte, cuando una biblioteca define tipos básicos sin propiedades garantizados más allá de los tipos con nombres similares en el estándar (piensa INT, GLint, gint, LPSTR, u32, u_int, etc.), el propósito es o bien:

  1. para "marca" su código con una gran cantidad de apretada la dependencia a la biblioteca por lo que es un dolor de reutilizar el código sin la biblioteca, o
  2. ignorancia que la norma C proporciona los tipos apropiados para las necesidades de la biblioteca.

Basado en uno de mis principios favoritos "Nunca atribuya a la malicia lo que se puede explicar adecuadamente por la estupidez", puede ir con el n. ° 2, pero realmente depende de usted.

personalmente cada vez que la codificación a una API tal, lanzo a cabo los tipos de biblioteca específica y utilizar los tipos naturales correctas (int, char *, uint32_t, etc.) en su lugar. Entonces es fácil adaptar mi código para usar sin la biblioteca si alguna vez lo necesito, y el código es más legible para personas que no están familiarizadas con la biblioteca.

+0

Desacelerado con el "estándar C", OpenGL no es solo para C y no tiene nada que ver con C (o cualquier otro lenguaje de programación). :) No es una "biblioteca", es una API. – Kos

+0

No existe una API independiente del idioma. Seguramente podría intentar hacer versiones similares de la API para varios idiomas, con éxito mixto. (Buena suerte haciendo que la API de OpenGL tenga el mismo aspecto en Brainf * ck ..) Al crear una instancia de la API en un idioma en particular, debe seguir las convenciones de ese idioma, especialmente en términos de tipos. Muchos idiomas ni siquiera tienen tipos, y tratar de imponer una idea ridícula de 'GLint' sobre ellos en lugar de utilizar su forma nativa de representar enteros tendría a los usuarios del lenguaje en alto. C merece el mismo respeto. –

+0

@Kos: Es un estándar, con una especificación. La especificación está escrita de una manera independiente del idioma. @R: los encabezados de la plataforma OpenGL están escritos con C89 en mente. C89 no tenía typedefs para tipos integrales con tamaños exactos, como int32_t, por lo que tenían que definir los suyos propios. Además, tu 1.) es incorrecto. ¿Por qué alguien haría eso a propósito? Por lo general, cada vez que ves algo extraño, a menudo puedes culparlo por * código heredado *, no por malicia o estupidez. –

Cuestiones relacionadas