10
votes

Bit change sur un pointeur C?

Je suis au milieu de ce projet C que je souhaite rendre une mémoire très efficace. Dans plusieurs cas, j'utilise le vide * S d'une structure de tableau dynamique que j'ai écrite afin de tenir des bits. Je souhaite utiliser tous les 64 bits (dans ce cas).

J'ai vite compris que vous ne pouvez pas réellement faire une manipulation de bits sur un pointeur. Donc, ma solution était la suivante: xxx

Ceci fait le travail effectué, mais uniquement parce que sur mon ordinateur, les longs et les pointeurs sont égaux de taille. Sera-ce le cas dans toutes les architectures (ou la plupart) architectures?

et ma vraie question: Y a-t-il un moyen plus correct de faire une manipulation de bits sur un pointeur? J'avais pensé que Cette approche était quelque peu courante en C (bits d'emballage dans un vide *), mais je pouvais me tromper ...


5 commentaires

J'utiliserais uint64_t à la place de stdint.h


uint64_t serait trop gros si votre plate-forme a moins de 64 bits. Utilisez IntPTR_T et UInTPTR_T de la même en-tête.


@sambowry - On dirait que vous devez passer par stdint.h un peu plus proche.


Si vous vous attendez à l'utiliser sous la forme d'un champ de bit de 64 bits, la compilation d'une plate-forme 32 bits va briser des objets, peu importe ce que vous le jetez. Comme je l'ai mentionné dans ma réponse ci-dessous, vous souhaitez déclarer une union du pointeur avec n'importe quel bitfield de taille dont vous avez besoin, de sorte que le champ est la bonne taille quelle que soit la plate-forme que vous ciblez.


Pourquoi auriez-vous besoin de telles manipulations de pointeur en premier lieu? Leur seule utilisation légitime est à des fins d'alignement et qui a des solutions de contournement qui ne nécessitent pas de coulée et d'entiers.


4 Réponses :


17
votes

Si votre compilateur prend en charge IT, C99'S Indice fournit le intPTR_T et uintptr_t Types qui devrait être suffisamment large pour tenir Un pointeur sur votre système, mais sont des entiers, vous pouvez donc faire une manipulation de bits. Cela ne peut pas vraiment devenir beaucoup plus portable que cela, si c'est ce que vous recherchez.


3 commentaires

Quoi qu'il en soit, vous n'avez probablement pas besoin d'une solution entièrement portable. N'importe quel bit-Twiddling qui tente de stocker des drapeaux dans les bits inférieurs des pointeurs est nécessairement spécifique à la plate-forme, car il s'appuie sur des hypothèses sur l'alignement des objets. Donc, le questionneur devra probablement faire du travail (ou au moins des recherches) lors du port vers une nouvelle plate-forme de toute façon.


@Steve - S'il fait un peu de clause sur un pointeur, j'espère certainement qu'il n'est pas la déséroférance plus tard. Cela ressemble à un cauchemar de portabilité. S'il faisait cela, je doute qu'il soit posé sur la portabilité de ses opérations.


Pourriez-vous expliquer la ou les différences entre intPTR_T et uintptr_t ?



2
votes

Déclarez une union du pointeur et un bitfield.


2 commentaires

Vous auriez toujours besoin de savoir à quel point pour créer le Bitfield, de sorte que votre autre champ aurait besoin d'être un intPTR_T. Je ne suis pas sûr que ce casting soit plus lisible.


Vous rendez le Bitfield aussi important que nécessaire pour votre autre fins. Le compilateur veillera alors à ce que la structure soit suffisamment grande de manière à ce que le pointeur et le bitfield soient amusés. Cette situation est exactement ce que sont les syndicats.



8
votes

Si vous devez faire ce genre de manipulation sur des pointeurs, vous pouvez les jeter à intPTR_T et uintptr_t , qui est tous deux trouvé dans stdint.h . Ceux-ci sont garantis comme étant définis comme type d'entier spécifique à la plate-forme avec suffisamment de bits pour contenir un pointeur.

Il y a aussi ptrdiff_t là-bas, si vous avez besoin de quelque chose pour contenir la différence entre deux pointeurs.


1 commentaires

Et si votre compilateur ne supporte pas STDINT.H ( COULD Microsoft COULD ), la réponse et les commentaires suivants ont des liens vers plusieurs que vous pourriez décider d'utiliser: Stackoverflow.com / Questions / 126279 / ...



3
votes

Je pense que vous essayez de résoudre le mauvais problème. Le vrai problème est là ici:

J'utilise le vide * S d'une dynamique structure de tableau que j'ai écrit afin de tenir des bits.

n'utilisez pas de pointeurs de vide pour tenir des bits. Utilisez des pointeurs vides pour contenir des pointeurs. Utilisez des entiers non signés pour tenir des bits.


3 commentaires

Je ne suis pas sûr que j'accepterais que c'est pratique de réécrire une structure de données complète et de toutes ses fonctions associées afin de pouvoir stocker des valeurs non du pointeur. Là encore, peut-être que si j'avais écrit ma structure de données plus correctement, je n'aurais pas eu ce problème.


Eh bien, vous pouvez utiliser Excel comme base de données si vous souhaitez éviter le travail supplémentaire d'apprentissage sur les bases de données, mais sera-t-il une bonne idée à long terme? Sachez que les conversions et le dos du pointeur à int-int sont une implémentation totalement définie, et si vous ne faites pas attention à la manipulation, vous pouvez terminer par un comportement indéfini. Votre structure était destinée à stocker des pointeurs. Pourquoi ne pas écrire une source de données BitStore spécialisée pour stocker des bits, avec tout le bit Twiddling déjà à l'intérieur, de sorte que vous n'êtes pas obligé de le prendre en charge sur chaque appel?


-1 pour prêcher à l'OP. On dirait qu'il sait ce qu'il veut.