2010-09-28 9 views
10

Estoy diseñando una clase Buffer cuyo objetivo es representar una porción de memoria.void * o char * para representación de buffer genérico?

Mi memoria intermedia subyacente es char* (bueno, boost::shared_array<char> en realidad, pero en realidad no importa).

estoy atascado en decidir qué prototipo para elegir para mi constructor:

¿Debo ir con:

Buffer(const void* buf, size_t buflen); 

O con:

Buffer(const char* buf, size_t buflen); 

O algo más?

Lo que se suele hacer, y por qué?

+0

@Luca Matteis: Tengo la intención de proporcionar el intercambio implícito de memoria. Pero eso es bastante fuera de tema. – ereOn

+1

Hay una desafortunada transmogrificación, impulsada por Unicode, en la que 'char' se está convirtiendo en sinónimo de' octet' y tiene poco que ver con 'character'. Esta pregunta es sintomática de ese cambio; He tenido la tentación de 'typedef char octet;' a veces para hacer que el código sea menos engañoso. – msw

+0

@msw: además de la compatibilidad de tipo con literales de cadena, ¿hay alguna razón para usar "char", a diferencia de "char firmado" o "char sin signo"? Me parece un tipo bastante inútil. – supercat

Respuesta

11

interfaz API es más claro para el usuario, si tiene memoria intermedia tipo void *, y la cadena tiene tipo char *. Compare las definiciones de funciones memcpy y strcpy.

+1

De hecho tiene sentido. – ereOn

6

preferiría char*, porque para mí, personalmente, juega mejor con ser "un buffer". void* parece más como "un puntero a No sé qué". Además, es lo que subyace, de todos modos.

+15

Un 'void *' no es un "puntero a No sé dónde", es un "puntero a No sé qué" :-) – paxdiablo

+0

@pax: Sí, creo que eso suena mejor (aunque inicialmente pensé que suena equivalente), así que lo cambié a "qué" –

+0

Pero un buffer genérico es exactamente eso: un buffer para "no sé qué". – 12431234123412341234123

14

Para el constructor y otras funciones de API, la ventaja de void* es que le permite a la persona que llama pasar un puntero a cualquier tipo sin tener que realizar un lanzamiento innecesario. Si tiene sentido que la persona que llama pueda pasar de cualquier tipo, entonces es preferible void*. Si realmente solo tiene sentido que la persona que llama pueda pasar el char*, entonces use ese tipo.

+0

Estoy de acuerdo contigo :) – vulkanino

8

Generalmente utilizo unsigned char como la estructura subyacente (no quiero firmar para estropear mi búfer, sé cuál es el motivo). Sin embargo por lo general se typedef:

typedef unsigned char byte; 

Y a continuación, se refieren a ella como byte* que transmite claramente el significado en mi opinión, mejor que cualquiera de char* o al menos void*.

+1

No puedo hacer +1 con la suficiente fuerza. Esto alivia todos los errores con 'char' como' char buf [42]; ... if (buf [i] == 0xFF) // * nunca es verdad * ' – Thanatos

6

Me gustaría recomendar uint8_t, que se define en stdint.h. Básicamente es lo mismo que el "typedef byte de char sin signo"; que otros han estado recomendando, pero tiene la ventaja de ser parte del estándar C.

En cuanto a void *, Yo sólo uso que para el polimorfismo. es decir. Solo llamaría a algo como un puntero vacío si aún no supiera a qué tipo de cosas apunta. En tu caso, tienes un conjunto de bytes, así que lo etiquetaría como tal usando uint8_t * como tipo.

2

Prefiero unsigned char * o uint8_t * para implementaciones de búfer, ya que void * tiene la molesta restricción de que no puede realizar cálculos de puntero en él. Así que si desea procesar algunos datos en un cierto desplazamiento de la memoria intermedia, o simplemente romper su memoria intermedia en trozos o lo que sea, usted está atascado de fundición a algún otro tipo de todos modos para hacer los cálculos.

prefiero unsigned char * o uint8_t * más sencillo char * debido a la special rules respecto aliasing y char *, que tiene el potencial de pessimize seriamente algunos bucles que trabajan en sus memorias intermedias.

Cuestiones relacionadas