2009-12-04 13 views
9

Sono nel mezzo di questo progetto C che desidero rendere molto efficiente la memoria. In molti casi, sto usando il void * s di una struttura di array dinamica che ho scritto per contenere bit. Vorrei usare tutti i 64 bit (in questo caso).Il bit si sposta su un puntatore C?

Mi sono subito reso conto che non è possibile eseguire alcuna manipolazione di bit su un puntatore. Così la mia soluzione era il seguente:

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

Questo ottiene il lavoro fatto, ma solo perché sul mio computer, anela e puntatori sono uguali in termini di dimensioni. Sarà questo il caso in tutte (o la maggior parte) delle architetture?

E la mia vera domanda: Esiste un modo più corretto di manipolare i bit su un puntatore? Avevo pensato che questo approccio era un po 'comune in C (imballaggio bit in un void *), ma potrei essere scambiato ...

+0

Vorrei usare uint64_t invece di stdint.h – sambowry

+2

uint64_t sarebbe troppo grande se la tua piattaforma ha meno di puntatori a 64 bit. Usa intptr_t e uintptr_t dalla stessa intestazione. – tgamblin

+0

@sambowry - Sembra che tu debba passare attraverso 'stdint.h' un po 'più vicino. –

risposta

15

Se il compilatore supporta, <stdint.h> colpo di testa di C99 fornisce i tipi intptr_t e uintptr_t che dovrebbe essere abbastanza grande da contenere un puntatore sul sistema, ma sono numeri interi, quindi è possibile eseguire la manipolazione dei bit. Non può davvero diventare molto più portatile di così, se è quello che stai cercando.

+0

In ogni caso, probabilmente non hai bisogno di una soluzione completamente portatile. Qualsiasi bit-twiddling che tenta di archiviare i flag nei bit inferiori dei puntatori è necessariamente specifico della piattaforma, poiché si basa su ipotesi sull'allineamento degli oggetti. Quindi l'intervistatore dovrà probabilmente fare del lavoro (o almeno una ricerca) quando effettuerà il porting su una nuova piattaforma. –

+0

@Steve - Se sta facendo un po 'di giocherellando con un puntatore, spero certamente che non lo stia differenziando più tardi. Sembra solo un incubo per la portabilità.Se lo stava facendo, dubito che si chiederebbe la portabilità delle sue operazioni. –

+1

Puoi spiegare la differenza (s) tra 'intptr_t' e' uintptr_t'? – DRz

2

Dichiarare un'unione del puntatore e un campo bit.

+1

Avresti ancora bisogno di sapere quanto è grande per rendere il bitfield, quindi il tuo altro campo dovrebbe essere un intptr_t. Non sono sicuro se questo o il casting sarebbero più leggibili. – tgamblin

+1

Si rende il bitfield grande quanto deve essere per gli altri scopi. Il compilatore si assicurerà quindi che la struttura sia abbastanza grande in modo che il più grande fuori dal puntatore e dal bitfield si adattino a esso. Questa situazione è esattamente ciò che i sindacati sono per. –

7

Se è necessario eseguire questo tipo di manipolazione sui puntatori, è possibile trasmetterli a intptr_t e uintptr_t, entrambi possono essere trovati in stdint.h. Questi sono garantiti per essere definiti come il tipo intero specifico della piattaforma con abbastanza bit per contenere un puntatore.

C'è anche ptrdiff_t lì, se avete bisogno di qualcosa per tenere la differenza tra due puntatori.

+4

E se il tuo compilatore non supporta stdint.h (* cough * Microsoft * cough *), la seguente risposta SO e i commenti hanno collegamenti a diversi che potresti decidere di utilizzare: http://stackoverflow.com/questions/126279/ c99-stdint-h-header-e-ms-visual-studio/126285 # 126285 –

3

Penso che tu stia cercando di risolvere il problema sbagliato. Il vero problema è proprio qui:

Sto usando il void * s di una struttura matrice dinamica che ho scritto per bit attesa.

Non utilizzare puntatori di vuoti per contenere i bit. Usa puntatori void per contenere puntatori. Utilizzare numeri interi senza segno per contenere i bit.

+0

Non sono sicuro di essere d'accordo sul fatto che sia pratico riscrivere un'intera struttura di dati e tutte le sue funzioni associate per poter memorizza valori non puntatori. Poi di nuovo, forse se avessi scritto la mia struttura dati più correttamente non avrei avuto questo problema. – MADgood

+0

Bene, puoi usare Excel come database se vuoi evitare il lavoro aggiuntivo di apprendimento sui database, ma sarà una buona idea a lungo termine? Tieni presente che le conversioni e il ritorno da puntatore a int sono completamente definiti dall'implementazione e, se non stai attento con la gestione, potresti finire con un comportamento indefinito. La tua struttura era destinata a memorizzare puntatori. Perché non scrivere una infrastruttura di BitStore specializzata per archiviare bit, con tutti i bit che girano già dentro, quindi non devi preoccuparti di questo per ogni chiamata? – Secure

+0

-1 per predicare all'OP. Sembra che lui sappia quello che vuole. –

Problemi correlati