2009-12-04 13 views
9

Ich bin mitten in diesem C-Projekt, das ich sehr speicher effizient machen möchte. In einigen Fällen verwende ich die void * s einer dynamischen Array-Struktur, die ich geschrieben habe, um Bits zu halten. Ich möchte alle 64 (in diesem Fall) Bits verwenden.Bitverschiebungen auf einem C-Zeiger?

Ich erkannte bald, dass Sie tatsächlich keine Bit-Manipulation auf einem Zeiger tun können. So war meine Lösung des folgenden:

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

Dies erhält die Arbeit erledigt, aber nur, weil auf meinem Computer, longs und Zeiger sind gleich groß. Wird dies in allen (oder den meisten) Architekturen der Fall sein?

Und meine eigentliche Frage: Gibt es eine richtigere Möglichkeit, Bit-Manipulation auf einem Zeiger zu tun? Ich hatte gedacht, dass dieser Ansatz in C etwas üblich war (Bits in einen void * Verpackung), aber ich könnte falsch sein ...

+0

Ich würde Uint64_t stattdessen von stdint.h – sambowry

+2

Uint64_t wäre zu groß, wenn Ihre Plattform weniger als 64-Bit-Zeiger hat. Verwenden Sie intptr_t und uintptr_t aus derselben Kopfzeile. – tgamblin

+0

@sambowry - Sieht so aus, als müssten Sie 'stdint.h' etwas näher kommen. –

Antwort

15

Wenn Ihr Compiler unterstützt, bietet <stdint.h> Header C99 die intptr_t und uintptr_t Typen, sollte groß genug sein, um einen Zeiger auf Ihrem System zu halten, aber sind ganze Zahlen, so können Sie Bit-Manipulation tun. Es kann nicht wirklich viel tragbarer als das, wenn das ist, was Sie suchen.

+0

Wie auch immer, Sie brauchen wahrscheinlich keine vollständig portable Lösung. Jedes Bit-Twiddling, das versucht, Flags in den unteren Bits von Zeigern zu speichern, ist notwendigerweise plattformspezifisch, da es auf Annahmen über die Objektausrichtung beruht. Daher wird der Fragesteller wahrscheinlich bei der Portierung auf eine neue Plattform etwas arbeiten (oder zumindest forschen) müssen. –

+0

@Steve - Wenn er etwas an einem Zeiger dreht, hoffe ich, dass er es später nicht dereferenziert. Das hört sich einfach nach Portabilität-Albtraum an.Wenn er das tun würde, bezweifle ich, dass er nach der Tragbarkeit seiner Operationen fragen würde. –

+1

Können Sie die Unterschiede zwischen 'intptr_t' und' uintptr_t' erklären? – DRz

2

Deklarieren Sie eine Union des Zeigers und eines Bitfeldes.

+1

Sie müssten immer noch wissen, wie groß das Bitfeld ist, also müsste Ihr anderes Feld ein intptr_t sein. Ich bin mir nicht sicher, ob dies oder Casting besser lesbar wäre. – tgamblin

+1

Sie machen das Bitfeld so groß, wie es für Ihre anderen Zwecke benötigt wird. Der Compiler wird dann sicherstellen, dass die Struktur groß genug ist, so dass die größeren aus dem Zeiger und dem Bitfeld darin passen. Genau dafür sind Gewerkschaften da. –

7

Wenn Sie diese Art von Manipulation an Zeigern vornehmen müssen, können Sie sie in intptr_t und uintptr_t umwandeln, die beide in stdint.h gefunden werden können. Diese sind garantiert als der plattformspezifische Integer-Typ mit genügend Bits definiert, um einen Zeiger zu halten.

Es ist auch ptrdiff_t drin, wenn Sie etwas brauchen, um den Unterschied zwischen zwei Zeigern zu halten.

+4

Und wenn Ihr Compiler stdint.h (* hust * Microsoft * hust *) nicht unterstützt, haben die folgenden SO-Antworten und Kommentare Links zu mehreren, die Sie möglicherweise verwenden möchten: http://stackoverflow.com/questions/126279/ c99-stdint-h-header-und-ms-visual-studio/126285 # 126285 –

3

Ich denke, Sie versuchen, das falsche Problem zu lösen. Das eigentliche Problem ist hier richtig:

ich die void * s einer dynamischen Arraystruktur verwende ich, um halten Bits geschrieben.

Verwenden Sie keine void-Zeiger, um Bits zu halten. Verwenden Sie void pointer, um Zeiger zu halten. Verwenden Sie vorzeichenlose Ganzzahlen, um Bits zu halten.

+0

Ich bin mir nicht sicher, ich würde zustimmen, dass es praktisch ist, eine gesamte Datenstruktur und alle damit verbundenen Funktionen neu schreiben zu können Speichern Sie Zeigerwerte. Andererseits hätte ich vielleicht, wenn ich meine Datenstruktur korrekter geschrieben hätte, dieses Problem nicht gehabt. – MADgood

+0

Nun, Sie können Excel als Datenbank verwenden, wenn Sie die zusätzliche Arbeit des Lernens über Datenbanken vermeiden wollen, aber wird es auf lange Sicht eine gute Idee sein? Beachten Sie, dass die Conversions von Pointer zu Int und die Implementierung von Backs vollständig implementiert sind. Wenn Sie mit der Verarbeitung nicht vorsichtig sind, können Sie in nicht definiertem Verhalten enden. Ihre Struktur sollte Zeiger speichern. Warum schreibst du nicht eine BitStore-Datenstruktur, die darauf spezialisiert ist, Bits zu speichern, wobei all das Bit bereits drinnen ist, so dass du dich nicht bei jedem Anruf darum kümmern musst? – Secure

+0

-1 für das Predigen an das OP. Klingt, als wüsste er, was er will. –