2009-12-04 7 views
9

Estoy en el medio de este proyecto C que deseo hacer que la memoria sea muy eficiente. En varios casos, estoy usando el vacío * s de una estructura de matriz dinámica que escribí para contener bits. Deseo usar los 64 bits (en este caso).¿Cambios de bits en un puntero C?

Pronto me di cuenta de que en realidad no se puede manipular un bit en un puntero. Así que mi solución fue la siguiente:

void *p; 
((unsigned long)p) << 4; 
((unsigned long)p) & 3; 

Esto hace el trabajo, pero sólo porque en mi equipo, largos y punteros son iguales en tamaño. ¿Será este el caso en todas (o la mayoría) de las arquitecturas?

Y mi verdadera pregunta: ¿Hay una manera más correcta de hacer la manipulación de bits en un puntero? había pensado que este enfoque era algo común en C (bits en un vacío de embalaje *), pero podría estar equivocado ...

+0

Usaría uint64_t en lugar de stdint.h – sambowry

+2

uint64_t sería demasiado grande si su plataforma tiene punteros de menos de 64 bits. Use intptr_t y uintptr_t desde el mismo encabezado. – tgamblin

+0

@sambowry - Parece que necesitas pasar por 'stdint.h' un poco más cerca. –

Respuesta

15

Si su compilador soporta, cabecera de C99 <stdint.h> proporciona los intptr_t y uintptr_t tipos que deben ser lo suficientemente grande como para mantener un puntero en su sistema, pero son enteros, por lo que puede hacer la manipulación de bits. Realmente no puede ser mucho más portátil que eso, si eso es lo que estás buscando.

+0

De todos modos, es probable que no necesite una solución totalmente portátil. Cualquier movimiento de bits que intente almacenar indicadores en los bits inferiores de los indicadores es necesariamente específico de la plataforma, ya que se basa en suposiciones sobre la alineación del objeto. Por lo tanto, es probable que el consultante tenga que hacer algún trabajo (o al menos investigación) cuando transfiera a una nueva plataforma de todos modos. –

+0

@Steve - Si él está haciendo algo moviendo un puntero, ciertamente espero que no lo esté desreferenciando más tarde. Eso suena como una pesadilla de portabilidad.Si él estaba haciendo eso, dudo que pregunte sobre la portabilidad de sus operaciones. –

+1

¿Podría explicar la (s) diferencia (s) entre 'intptr_t' y' uintptr_t'? – DRz

2

Declara una unión del puntero y un campo de bits.

+1

Aún necesitaría saber qué tan grande era para hacer el campo de bits, por lo que su otro campo debería ser un intptr_t. No estoy seguro de si esto o el casting serían más legibles. – tgamblin

+1

Hace que el campo de bits sea tan grande como debe ser para sus otros fines. El compilador se asegurará entonces de que la estructura sea lo suficientemente grande para que encaje en ella el puntero y el campo de bits más grandes. Esta situación es exactamente para lo que son los sindicatos. –

7

Si necesita hacer este tipo de manipulación en los punteros, puede convertirlos a intptr_t y uintptr_t, los cuales se pueden encontrar en stdint.h. Se garantiza que se definirán como el tipo de entero específico de plataforma con suficientes bits para contener un puntero.

También hay ptrdiff_t allí, si necesita algo para mantener la diferencia entre dos punteros.

+4

Y si su compilador no es compatible con stdint.h (* tos * Microsoft * tos *), la siguiente respuesta SO y los comentarios tienen enlaces a varios que puede decidir utilizar: http://stackoverflow.com/questions/126279/ c99-stdint-h-header-and-ms-visual-studio/126285 # 126285 –

3

Creo que estás tratando de resolver el problema. El problema real está aquí:

estoy usando el void * s de una dinámica estructura serie que escribí con el fin de bits de retención.

No utilice los punteros vacíos para contener los bits. Use punteros vacíos para mantener los punteros. Use enteros sin signo para contener bits.

+0

No estoy seguro de que acepte que es práctico volver a escribir una estructura de datos completa y todas sus funciones asociadas para poder almacenar valores no punteros. Por otra parte, quizás si hubiera escrito mi estructura de datos de forma más correcta, no habría tenido este problema. – MADgood

+0

Bueno, puede usar Excel como base de datos si quiere evitar el trabajo adicional de aprender sobre bases de datos, pero ¿será una buena idea a largo plazo? Tenga en cuenta que las conversiones puntero-a-int y la parte posterior están completamente definidas por la implementación, y si no tiene cuidado con el manejo, puede terminar con un comportamiento indefinido. Su estructura estaba destinada a almacenar punteros. ¿Por qué no escribir una estructura de datos de BitStore especializada para almacenar bits, con todos los bits funcionando ya dentro, por lo que no tiene que preocuparse por cada llamada? – Secure

+0

-1 para predicar al OP. Parece que sabe lo que quiere. –