Posso fare aritmetica su void * puntatori in c?
-
26-09-2019 - |
Domanda
è valido
void *p = &X; /* some thing */
p += 12;
E se sì, cosa indica P ora? Ho un codice (di terze parti) che lo fa (e compila in modo pulito) e la mia ipotesi è che il vuoto * sia stato trattato come un carattere *. Il mio fidato K&R è silenzioso (ish) sull'argomento
EDIT: la mia piccola app di test funziona bene su GCC 4.1.1 e tratta void * come char *. Ma g ++ barfs
So come farlo correttamente. Devo sapere se devo pulire questa base di codice per trovare tutti i luoghi.
BTW GCC -Oppetic lancia un avvertimento
Riepilogo:
La specifica C è ambigua. Dice che in termini di rappresentazione e utilizzo come parametri della funzione void* = char*. Ma è silenzioso riguardo all'aritmetica del puntatore.
- GCC (4) lo consente e lo tratta come char *
- G ++ lo rifiuta
- GCC -Pedantic ne avverte
- VS2010 Sia C che C ++ lo rifiuta
Soluzione
Dipende dal compilatore. Quelli che lo consentono di considerare la dimensione di ( *(void *)) come 1.
EDIT: è solo per l'aritmetica del puntatore vuoto. Non avrebbe senso usare in questo caso passaggi di dimensione (int) o di 0. Le aspettative comuni di qualcuno che lo usa sarebbe il più piccolo passo possibile.
Altri suggerimenti
No, questo non è legale. UN void*
non può essere arbitrariamente incrementato. Deve prima essere lanciato su un tipo specifico.
Se si desidera incrementarlo con un numero specifico di byte, questa è la soluzione che uso.
p = ((char*)p) + 12;
Il char
Il tipo è conveniente perché ha una dimensione definita di 1 byte.
MODIFICARE
È interessante notare che funziona su GCC con un avvertimento. Ho testato su Visual Studio 2010 e verificato che non si compila. La mia comprensione limitata dello standard direbbe che GCC nell'errore qui. Puoi aggiungere i seguenti flag di compilation
-Wall -ansi -pedantic
Per citare dalle specifiche:
§6.5.6/2: Per in aggiunta, entrambi gli operandi devono avere un tipo aritmetico o un operando deve essere un puntatore a un tipo di oggetto e l'altro deve avere un tipo di intero. (L'incremento equivale all'aggiunta di 1.)
Un puntatore al vuoto non è un puntatore a un tipo di oggetto, secondo questi estratti:
§6.2.5/1: [...] i tipi sono partizionati in tipi di oggetti (tipi che descrivono completamente gli oggetti), tipi di funzioni (tipi che descrivono le funzioni) e tipi incompleti (tipi che descrivono gli oggetti ma mancano di informazioni necessarie per determinare le loro dimensioni).
§6.2.5/19: Il tipo di vuoto comprende un set vuoto di valori; È un tipo incompleto che non può essere completato.
Pertanto, l'aritmetica del puntatore è non definito per puntatore a vuoto i tipi.
La tua ipotesi è corretta.
Nello standard ISO C99, Sezione 6.2.5 Paragrafo 26, dichiara che i puntatori vuoti e i puntatori del personaggio avranno la stessa rappresentazione e requisiti di allineamento (parafrasando).
Potresti voler dare un'occhiata alla risposta votata in alto per questa domanda
Non credo che tu possa, perché non ne conosce il tipo, quindi non può cercare la quantità corretta di byte.
Lancialo prima a un tipo, cioè (int)
.