L'aritmetica dei puntatori quando vuoto ha sconosciuta dimensione [chiusa]
-
16-09-2019 - |
Domanda
In Visual Studio C ++ versione 9 (e probabilmente altre versioni troppo), il seguente codice:
int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;
error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size
Questo codice funziona in GCC, che tratta sizeof(void)
come 1
.
C'è qualche modo a questa limitazione, come colata esplicitamente char *
per scopi di puntatori aggiunge alla confusione (void *
è ben riconosciuto e usato come un puntatore alla memoria senza tipo grezzo).
Update0
- Si prega di notare, io sono ben consapevole del esistenza della norma.
- I vuole per fare puntatore prime aritmetica.
- Colgo
sizeof(void)
a mostrare che io sono ben consapevole del fatto che non è1
è il causa del problema. - Il codice esempio è semplicemente quello di dimostrare ciò che è necessaria per generare gli errori.
- So che questo non è un modo "normale", per usare
void
, ma questo è C, e queste cose succedono. - Sì, la gente ha bisogno di fare questo a basso livello. Io non sono il motivo per cui dopo, sto cercando il modo. Se volete sapere il motivo per cui, date uno sguardo ad alcuni dei sorgenti del kernel, o il vostro glibc amichevole.
Update1
Sembra che questa domanda ha generato una grande confusione. La questione non è di perché avere sizeof(void) == 1
non è standard, ma cosa fare quando non lo è.
Nel caso che puntatore singolo byte aritmetica che deve essere fatto, si scopre che la fusione per char *
è la risposta corretta, non perché *(void *)
non ha dimensioni, ma perché lo standard di fatto garantisce che *(char *)
è sempre 1
. Pertanto l'uso di char *
è sempre corretta e congruente con void *
con l'estensione GCC ai fini del greggio puntatori.
Per rafforzare ulteriormente il punto, void *
è la scelta corretta per puntatori a Senza tipo di memoria, e char *
sia del tipo a getto a per greggio puntatori .
Soluzione 8
Sembrerebbe il risposta corretta è utilizzare char *
per puntatori, perché sizeof(char)
è sempre definita come 1, e ad essere della migliore granularità indirizzabile su qualsiasi piattaforma.
Così, in breve, non v'è alcun modo per aggirare la limitazione, char *
è in realtà il modo corretto per farlo.
Matthias Wandel avuto la risposta giusta ma con una giustificazione diversa.
Altri suggerimenti
Incremento un puntatore si suppone tecnicamente ad incrementarlo con qualsiasi dimensione di cosa che la sua punta a. punti vuoto al nulla, quindi la dimensione è sconosciuta.
La sua una finezza per alcuni compilatori per far si incrementa puntatori void.
Casting è fastidioso, perché si deve o lanci a un altro puntatore, e poi di nuovo, o fare qualcosa scomodi come (*(char *)&voidptr) += 6
Personalmente, avevo appena dichiareremo come char *
a fini di aritmetica
Nel linguaggio C sizeof
non può essere applicato ai tipi incompleti. void
è un tipo incompleto, che è il motivo per cui non è possibile utilizzare come operando di sizeof
.
Pointer aritmetica dei puntatori void *
non è supportata anche in C. Per essere utilizzato con puntatori puntatore ha per puntare ad oggetto tipo, che non è void
.
GCC permette sia come un'estensione del linguaggio strano.
void *
stanno a significare "puntatore a sconosciuto"
L'aggiunta di 6 a un puntatore nullo è quindi definito, perché si sta chiedendo al compilatore di avanzare il puntatore da "la dimensione di 6 oggetti sconosciuti".
Non si dovrebbe fare di esso.
Ci sono due domande differenti qui. Il primo è per void
, e la seconda per void*
. Essi sono diversi tipi, e hanno poco in comune accanto al nome.
void
viene utilizzato principalmente per le dichiarazioni di funzione / definizioni (come il tipo di ritorno o per significare "non accetta argomenti"). Non si può mai forse avere un oggetto di tipo void
. Mai. Quindi è difficile vedere la necessità di scoprire la dimensione di tale oggetto inesistente. comportamento di GCC non è standard, e l'estensione intenzionale . Tuttavia, credo che hanno scelto sizeof(void) == 1
perché lo standard C ++ richiede ogni oggetto a prendere almeno un byte di spazio.
void*
significa "puntatore a dati reali, ma senza le informazioni sul tipo di riferimento." E 'del tutto possibile avere void*
; e vi imbatterete in loro, un sacco. Tuttavia, poiché le informazioni di tipo viene ignorato non si può manipolare il puntatore molto. Ciò è di progettazione, perché se non sai quello che hai davvero non sa cosa si può fare con esso.
Ma se si desidera trattare la memoria, come un insieme di byte allora char*
fa. Un char
è un byte, in tutto il mondo. Una stringa di byte è un char*
. Se si trova questo strano, uso byte*
(dove si definisce byte
come qualcosa di simile unsigned char
).
Posso vedere l'errore sulla prima linea, almeno -? Avete sizeof (void) e dovrebbe essere sizeof (void *), non
Per puramente punta a dati grezzi e incrementando tale puntatore per il numero di byte che un blocco di dati occupa uso sempre char *
. Ho poi rifondere il puntatore a un puntatore struttura di dati rilevanti, una volta che ho bisogno di trattarlo come qualcosa di specifico. Incremento un void *
non è portabile tra i compilatori.
void * è ben riconosciuto e usato come un puntatore alla memoria senza tipo grezzo.
Una corretta. Non avendo un tipo non significa avere una dimensione sia.