Domanda

Mi piacerebbe sapere architetture che violano i presupposti Ho elencato di seguito.Inoltre, vorrei sapere se qualcuno dei presupposti è falso per tutte le architetture (cioè se qualcuno di essi è completamente sbagliato).

  1. sizeof(int *) == sizeof(char *) == sizeof(void *) == sizeof(func_ptr *)

  2. La rappresentazione in memoria di tutti i puntatori per una determinata architettura è la stessa indipendentemente dal tipo di dati puntato.

  3. La rappresentazione in memoria di un puntatore è la stessa di un numero intero della stessa lunghezza di bit dell'architettura.

  4. La moltiplicazione e la divisione dei tipi di dati del puntatore sono vietate solo dal compilatore.NOTA:Sì, lo so, non ha senso.Ciò che intendo è: esiste un supporto hardware per impedire questo utilizzo errato?

  5. Tutti i valori dei puntatori possono essere convertiti in un singolo numero intero.In altre parole, quali architetture utilizzano ancora segmenti e offset?

  6. Incrementare un puntatore equivale ad aggiungere sizeof(the pointed data type) all'indirizzo di memoria memorizzato dal puntatore.Se p è un int32* Poi p+1 è uguale all'indirizzo di memoria 4 byte dopo p.

Sono più abituato ai puntatori utilizzati in uno spazio di memoria virtuale contiguo.Per questo utilizzo, generalmente riesco a pensarli come indirizzi su una linea numerica.Vedi la domanda Stack Overflow Confronto dei puntatori.

È stato utile?

Soluzione

Non posso darti esempi concreti di tutti questi, ma farò del mio meglio.

sizeof(int *) == sizeof(char *) == sizeof(void *) == sizeof(func_ptr *)

Non conosco nessun sistema in cui I Sapere questo è falso, ma considera:

I dispositivi mobili spesso dispongono di una certa quantità di memoria di sola lettura in cui è memorizzato il codice del programma e simili.I valori di sola lettura (variabili const) possono plausibilmente essere archiviati nella memoria di sola lettura.E poiché lo spazio degli indirizzi della ROM potrebbe essere più piccolo del normale spazio degli indirizzi della RAM, anche la dimensione del puntatore potrebbe essere diversa.Allo stesso modo, i puntatori alle funzioni potrebbero avere dimensioni diverse, poiché potrebbero puntare a questa memoria di sola lettura in cui è caricato il programma e che altrimenti non può essere modificata (quindi i dati non possono essere archiviati al suo interno).

Quindi non conosco alcuna piattaforma su cui ho osservato che quanto sopra non è valido, ma posso immaginare sistemi in cui potrebbe essere il caso.

La rappresentazione in memoria di tutti i puntatori per una determinata architettura è la stessa indipendentemente dal tipo di dati puntato.

Pensa ai puntatori dei membri rispetto ai puntatori normali.Non hanno la stessa rappresentazione (o dimensione).Un puntatore membro è costituito da a this puntatore e un offset.

E come sopra, è concepibile che alcune CPU carichino dati costanti in un'area separata della memoria, che utilizza un formato puntatore separato.

La rappresentazione in memoria di un puntatore è la stessa di un numero intero della stessa lunghezza di bit dell'architettura.

Dipende da come viene definita la lunghezza di bit.:) UN int su molte piattaforme a 64 bit è ancora 32 bit.Ma un puntatore è di 64 bit.Come già detto, le CPU con un modello di memoria segmentata avranno puntatori costituiti da una coppia di numeri.Allo stesso modo, i puntatori dei membri sono costituiti da una coppia di numeri.

La moltiplicazione e la divisione dei tipi di dati del puntatore sono vietate solo dal compilatore.

In definitiva, solo tipi di dati dei puntatori esistere nel compilatore.Ciò con cui lavora la CPU non sono i puntatori, ma numeri interi e indirizzi di memoria.Quindi non c'è nessun altro posto dove queste operazioni sui tipi di puntatore Potevo essere proibito.Potresti anche chiedere alla CPU di vietare la concatenazione di oggetti stringa C++.Non può farlo perché il tipo stringa C++ esiste solo nel linguaggio C++, non nel codice macchina generato.

Tuttavia, per rispondere a ciò che tu Significare, cerca le CPU Motorola 68000.Credo che abbiano registri separati per numeri interi e indirizzi di memoria.Ciò significa che possono facilmente vietare tali operazioni insensate.

Tutti i valori dei puntatori possono essere convertiti in un singolo numero intero.

Sei al sicuro lì.Gli standard C e C++ garantiscono che ciò sia sempre possibile, indipendentemente dalla disposizione dello spazio di memoria, dall'architettura della CPU e qualsiasi altra cosa.Nello specifico garantiscono un mappatura definita dall'implementazione.In altre parole, puoi sempre convertire un puntatore in un numero intero e quindi riconvertire quell'intero per ottenere il puntatore originale.Ma i linguaggi C/C++ non dicono nulla su quale dovrebbe essere il valore intero intermedio.Dipende dal singolo compilatore e dall'hardware a cui si rivolge.

Incrementare un puntatore equivale ad aggiungere sizeof (il tipo di dati puntato) all'indirizzo di memoria memorizzato dal puntatore.

Ancora una volta, questo è garantito.Se si considera che concettualmente un puntatore non punta a un indirizzo, punta a an oggetto, allora questo ha perfettamente senso.Aggiungendo uno al puntatore lo farà ovviamente puntare a Prossimo oggetto.Se un oggetto è lungo 20 byte, l'incremento del puntatore lo sposterà di 20 byte, in modo che si sposti al successivo oggetto.

Se un puntatore fosse semplicemente un indirizzo di memoria in uno spazio di indirizzi lineare, se fosse fondamentalmente un numero intero, allora incrementandolo si aggiungerebbe 1 all'indirizzo, cioè si sposterebbe al successivo byte.

Infine, come ho accennato in un commento alla tua domanda, tieni presente che il C++ è solo un linguaggio.Non importa su quale architettura è compilato.Molte di queste limitazioni possono sembrare oscure sulle moderne CPU.Ma cosa succede se prendi di mira le CPU del passato?E se prendessi di mira le CPU del prossimo decennio?Non sai nemmeno come funzioneranno, quindi non puoi dare molto per scontato al riguardo.Cosa succede se stai prendendo di mira una macchina virtuale?Esistono già compilatori che generano bytecode per Flash, pronti per essere eseguiti da un sito web.Cosa succede se vuoi compilare il tuo codice sorgente C++ in Python?

Rimanere entro le regole specificate nello standard garantisce che il tuo codice funzionerà Tutto questi casi.

Altri suggerimenti

Non ho specifiche esempi reali in mente, ma l ' "autorità" è lo standard C. Se qualcosa non è richiesto dalla norma, si può costruire un conforme attuazione che non riesce intenzionalmente di rispettare eventuali altre ipotesi. Alcune di queste ipotesi sono vere più delle volte solo perché è conveniente per implementare un puntatore come un intero che rappresenta un indirizzo di memoria che può essere recuperato direttamente dal processore ma questo è solo un conseguente di "comodo" e non può essere ritenuto come una verità universale.

  1. Non richiesto dallo standard (vedi questa domanda ). Per esempio, sizeof(int*) può essere diverso da size(double*). void* è garantito per essere in grado di memorizzare qualsiasi valore del puntatore.
  2. Non richiesto dalla norma. Per definizione, la dimensione è una parte di rappresentazione. Se la dimensione può essere diverso, la rappresentazione può essere diversa.
  3. Non necessariamente. Infatti, "la lunghezza po 'di architettura" è una dichiarazione vaga. Che cosa è un processore a 64 bit, in realtà? E 'il bus di indirizzo? Dimensioni di registri? Bus dati? Cosa?
  4. Non ha senso per "moltiplicare" o "dividere" un puntatore. E 'vietato dal compilatore, ma è possibile, naturalmente, moltiplicare o dividere la rappresentazione sottostante (che in realtà non ha senso per me) e che si traduce in un comportamento indefinito.
  5. Forse non capisco il tuo punto, ma tutto in un computer digitale è solo una sorta di numero binario.
  6. Sì; tipo. E 'garantito per puntare a una posizione che è un sizeof(pointer_type) più lontano. Non è necessariamente equivalente aritmetica aggiunta di un numero (cioè più è un concetto logico qui. La rappresentazione effettiva è specifica architettura)

Per 6 .: un puntatore non è necessariamente un indirizzo di memoria. Si veda ad esempio " The Great Conspiracy Pointer " di Pila utente Overflow JALF :

  

Sì, ho usato la parola “indirizzo” nel commento di cui sopra. E 'importante capire che cosa voglio dire con questo. Non voglio dire “l'indirizzo di memoria in cui i dati sono fisicamente memorizzati”, ma semplicemente un abstract “qualsiasi cosa abbiamo bisogno, al fine di individuare il valore. L'indirizzo del Potrei essere qualsiasi cosa, ma una volta che l'abbiamo, possiamo sempre trovare e modificare i ".

E

  

puntatore non è un'indirizzo di memoria! Ne ho parlato in precedenza, ma diciamo di nuovo. I puntatori sono in genere attuata dal compilatore semplicemente come indirizzi di memoria, sì, ma non dovrebbe essere così. "

Alcuni ulteriori informazioni su puntatori dallo standard C99:

  • 6.2.5 §27 garantisce che void* e char* hanno rappresentazioni identiche, cioè possono essere usati indifferentemente senza conversione, cioè lo stesso indirizzo è indicato con lo stesso schema di bit (che non deve essere vero per altri tipi di puntatore )
  • 6.3.2.3 §1 stabilisce che qualsiasi puntatore a un tipo incompleto o oggetto può essere lanciato verso (e da) void* e ritorno e ancora valida; questo non include puntatori a funzione!
  • 6.3.2.3 § 6 afferma che void* può essere lanciato per (e da) interi e 7.18.1.4 §1 fornisce tipi apropriate intptr_t e uintptr_t; il problema: questi tipi sono opzionali - la norma menziona esplicitamente che non ci devono essere un tipo integer abbastanza grande da contenere in realtà il valore del puntatore

sizeof(char*) != sizeof(void(*)(void)? - Non su x86 in modalità 36 bit di indirizzamento (supportati su praticamente ogni CPU Intel Pentium dal 1)

"La rappresentazione in memoria di un puntatore è la stessa come numero intero della stessa lunghezza bit" - non c'è rappresentazione in memoria su qualsiasi architettura moderna; memoria tag non ha mai preso piede ed era già obsoleta prima di C è stato standardizzato. Memoria in realtà non ha nemmeno tenere interi, solo bit e discutibilmente parole (non byte;. Più memoria fisica non consente di leggere solo 8 bit)

"Moltiplicazione dei puntatori è impossibile" - 68000 famiglia; registri di indirizzi (quelli in possesso di puntatori) non ha sostenuto che IIRC.

"Tutti i puntatori possono essere espressi in numeri interi" -. Non su PIC

"Incremento una T * è equivalente ad aggiungere sizeof (T) per l'indirizzo di memoria" - vero per definizione. Anche equivalente a &pointer[1].

Non so gli altri, ma per DOS, l'assunzione in # 3 è falso. DOS è a 16 bit ed utilizza vari trucchi per mappare molti di più di 16 bit del valore della memoria.

  

La rappresentazione in memoria di un puntatore è uguale a un numero intero della stessa lunghezza di bit come architettura.

Credo che questo assunto è falso perché il 80186, per esempio, un puntatore a 32 bit si svolge in due registri (un offset registrare un un registro segmento), e che mezza parola è andato in che registrano le questioni durante l'accesso.

  

moltiplicazione e la divisione dei tipi di dati di puntatore sono proibiti solo dal compilatore.

Non si può moltiplicare o dividere i tipi. ; P

Non sono sicuro perché si vuole moltiplicare o dividere un puntatore.

  

Tutti i valori di puntatore può essere colate ad un singolo intero. In altre parole, ciò che le architetture ancora fare uso di segmenti e compensazioni?

Lo standard C99 permette puntatori verranno memorizzati nella intptr_t, che è di tipo intero. Quindi, sì.

  

incrementando un puntatore è equivalente ad aggiungere sizeof (il tipo di dati a punta) all'indirizzo memorizzato dal puntatore. Se p è un int32 * allora p + 1 è uguale all'indirizzo di memoria 4 byte dopo p.

x + y dove x è un T * e y è un numero intero è equivilent a (T *)((intptr_t)x + y * sizeof(T)) per quanto ne so. L'allineamento può essere un problema, ma imbottitura può essere fornito nel sizeof. Io non sono davvero sicuro.

In generale, la risposta a tutte le domande è " si ", ed è perché solo le macchine che implementano linguaggi popolari videro direttamente la luce del giorno e persistevano nel secolo corrente. Anche se gli standard linguistici si riservano il diritto di variare questi "invarianti", o asserzioni ma non e 'mai accaduto in prodotti reali, con la possibile eccezione degli articoli 3 e 4, che richiedono un po' di rideterminazione di essere universalmente vero.

E 'certamente possibile costruire modelli segmentati MMU, che corrispondono grosso modo con le architetture basate su capacità che erano popolari accademico negli anni passati, ma nessuna tale sistema è tipicamente visto uso comune con tali funzioni abilitate. Tale sistema potrebbe avere in conflitto con le affermazioni come probabilmente avrebbe avuto grandi puntatori.

Oltre a segmentato / capacità di MMU, che spesso hanno grandi puntatori, disegni più estreme hanno cercato di codificare i tipi di dati in puntatori. Pochi di questi sono stati mai costruito. (Questa domanda porta in primo piano tutte le alternative per la parola-oriented di base, un puntatore-is-a-word architetture.)

In particolare:

  1. La rappresentazione in memoria di tutti i puntatori per un dato architettura è la stessa indipendentemente dal tipo di dati puntato. La vera eccezione per i disegni del passato estremamente stravaganti che ha cercato di implementare la protezione non lingue fortemente tipizzato, ma a livello hardware.
  2. La rappresentazione in memoria di un puntatore è uguale a un numero intero della stessa lunghezza di bit come architettura. Forse, certamente una sorta di tipo integrale è la stessa, si veda LP64 vs LLP64 .
  3. moltiplicazione e la divisione dei tipi di dati di puntatore sono proibiti solo dal compilatore. e .
  4. Tutti i valori di puntatore può essere colate ad un singolo intero. In altre parole, ciò che le architetture ancora fare uso di segmenti e compensazioni? Niente utilizza segmenti e offset oggi, ma un int C spesso non è abbastanza grande, potrebbe essere necessario un long o long long di tenere un puntatore.
  5. incrementando un puntatore è equivalente ad aggiungere sizeof (il tipo di dati a punta) all'indirizzo memorizzato dal puntatore. Se p è un int32 * allora p + 1 è uguale all'indirizzo di memoria 4 byte dopo p. Sì.

E 'interessante notare che ogni architettura Intel CPU, vale a dire, ogni singolo PeeCee, contiene un'unità di segmentazione elaborato di epico, leggendario, complessità. Tuttavia, è in effetti disabilitato. Ogni volta che un OS PC stivali fino, imposta le basi del segmento a 0 e le lunghezze di segmento a ~ 0, annullamento dei fuori i segmenti e dando un modello di memoria piatta.

Ci sono stati un sacco di "parola rivolta" architetture nel 1950, 1960 e 1970. Ma non riesco a ricordare tutti gli esempi principali che hanno avuto un compilatore C. Ricordo la ICL / Three Rivers PERQ macchine nel 1980 che è stato parola rivolta e aveva uno scrivibile memoria di controllo (microcodice). Una delle sue istanze avuto un compilatore C e un sapore di Unix chiamata PNX , ma la compilatore C richiesto microcodice speciale.

Il problema di fondo è che char * tipi di parola indirizzata macchine sono scomodi, ma li si implementa. Spesso con sizeof(int *) != sizeof(char *) ...

È interessante notare che, prima di C c'era un linguaggio chiamato BCPL in cui il tipo di puntatore base era un indirizzo di parola; cioè, incrementando un puntatore ti ha dato l'indirizzo della parola successiva, e ptr!1 ti ha dato la parola a ptr + 1. C'era un operatore diverso per affrontare un byte:. ptr%42 se ricordo

EDIT: Non rispondere alle domande, quando il livello di zucchero nel sangue è bassa. Il tuo cervello (di certo, il mio) non funziona come previsto. :-(

nitpick Minor:

p è un Int32 * allora p + 1

è sbagliato, ha bisogno di essere Int32 non firmato, altrimenti andrà a capo a 2GB.

stranezza Interessante - ho ricevuto questo da l'autore del compilatore C per il chip Transputer - mi ha detto che per quel compilatore, NULL è stata definita come -2GB. Perché? Poiché il Transputer aveva un intervallo di indirizzi firmato: -2GB a + 2GB. Si può credere che? Incredibile non è vero?

Da allora ho incontrato diverse persone che mi hanno detto che la definizione di NULL come quello è rotto. Sono d'accordo, ma se non si finisce puntatori NULL essere nel bel mezzo del vostro intervallo di indirizzi.

Credo che la maggior parte di noi può essere contenti noi non stiamo lavorando transputer!

  

Vorrei sapere architetture che violano le ipotesi che ho   elencati qui di seguito.

Vedo che Stephen C menzionato macchine PERQ, e MSalters citato 68000s e PIC.

Sono deluso dal fatto che nessun altro in realtà ha risposto alla domanda nominando una fra le architetture strane e meravigliose che hanno conformi agli standard compilatori C che non si adattano alcuni presupposti ingiustificati.

  

sizeof (int *) == sizeof (char *) == sizeof (void *) == sizeof (func_ptr   *)?

Non necessariamente. Alcuni esempi:

La maggior parte dei compilatori per Harvard-architettura processori a 8 bit - PIC e 8051 e M8C - rendere sizeof (int *) == sizeof (char *), ma diversa da quella sizeof (func_ptr *).

Alcuni dei molto piccoli chip a quelle famiglie hanno 256 bytes di RAM (o meno) ma diversi kilobyte di PROGMEM (Flash o ROM), quindi i compilatori spesso fanno sizeof (int *) == sizeof (char *) pari a 1 (un singolo byte a 8 bit), ma sizeof (func_ptr *) pari a 2 (due byte di 8 bit).

Compilatori per molti dei chip più grandi le famiglie con pochi kilobyte di RAM e 128 o così kilobyte di PROGMEM rendono sizeof (int *) == sizeof (char *) pari a 2 (due byte di 8 bit), ma sizeof (func_ptr *) uguale a 3 (tre 8-bit byte).

Alcuni chip Harvard-architettura in grado di memorizzare esattamente un completo 2 ^ 16 ( "64Kbyte") di PROGMEM (Flash o ROM), e un altro 2 ^ 16 ( "64Kbyte") di RAM + I / O mappato in memoria. I compilatori per un chip make sizeof (func_ptr *) siano sempre 2 (due byte); ma spesso hanno un modo per rendere gli altri tipi di puntatori sizeof (int *) == sizeof (char *) == sizeof (void *) in AA "lungo PTR" 3 byte puntatore generico che ha il tocco in più di magia che indica se che i punti di puntatore si trasforma in RAM o PROGMEM. (Questo è il tipo di puntatore è necessario passare ad un "print_text_to_the_LCD ()" funzione quando si chiama quella funzione da molti subroutine diverse, a volte con l'indirizzo di una variabile stringa in un tampone che potrebbe essere ovunque in RAM, e altre volte con una sola di molte stringhe costanti che potrebbe essere ovunque nel PROGMEM). Tali compilatori hanno spesso parole chiave speciali ( "breve" o "vicino", "lungo" o "lontano") per permettere ai programmatori indicano specificamente tre diversi tipi di puntatori char nello stesso programma - stringhe costanti che hanno bisogno solo 2 byte per indicare dove in PROGMEM si trovano, stringhe non costanti che devono solo 2 byte per indicare dove nella RAM si trovano, e il tipo di puntatori 3 byte che "print_text_to_the_LCD ()" accetta.

La maggior parte dei computer costruiti negli anni 1950 e 1960 utilizzano un lunghezza di parola di 36 bit o 18 bit lunghezza di parola , con un 18-bit (o meno) bus indirizzi. Ho sentito dire che i compilatori C per tali computer utilizzano spesso 9-bit byte , con sizeof (int *) == sizeof (func_ptr *) = 2, che dà 18 bit, in quanto tutti gli interi e funzioni devono essere word-aligned; ma sizeof (char *) == sizeof (void *) == 4 di sfruttare PDP speciale 10 istruzioni che memorizzano questi puntatori in una parola piena 36-bit. Questa parola pieno 36 bit include un indirizzo di parola 18 bit, e un paio di bit delle altre 18-bit che (tra le altre cose) indicano la posizione di bit della punta a carattere all'interno quella parola.

  

La rappresentazione in memoria di tutti i puntatori per una certa architettura   è lo stesso indipendentemente dal tipo di dati indicato?

Non necessariamente. Alcuni esempi:

In una delle architetture ho parlato di unBove, puntatori sono disponibili in diverse dimensioni. Così come potevano forse avere "lo stesso" rappresentanza?

Alcuni compilatori su alcuni sistemi utilizzare "descrittori" per implementare puntatori di caratteri e altri tipi di puntatori . tale descrittore è diverso per un puntatore che punta al primo "char" in un "char big_array[4000]" che per un puntatore che punta al primo "char" in un "char small_array[10]", che sono forse diversi tipi di dati , anche quando la piccola matrice avviene a partire esattamente nella stessa posizione in memoria precedentemente occupata dalla matrice grande. Descrittori permettono tali macchine per catturare e intrappolare i buffer overflow che causano tali problemi su altre macchine.

Il "Low-Fat Puntatori" utilizzato nella Safelite e simili "soft processori" hanno analogo 'informazioni aggiuntive' sulle dimensioni del buffer della modalità operativa in. puntatori basso contenuto di grassi hanno lo stesso vantaggio di cattura e intrappolare i buffer overflow.

  

La rappresentazione in memoria di un puntatore è uguale a un numero intero   la stessa lunghezza bit come l'architettura?

Non necessariamente. Alcuni esempi:

"architettura etichettato" macchine, ciascuna parola di memoria ha alcuni bit che indicano se tale parola è un numero intero, o un puntatore, o qualcos'altro. Con queste macchine, guardando i bit indicatori vi direbbe se tale parola era un numero intero o un puntatore.

Ho sentito che Nova minicomputer hanno un "bit indirezione" in ogni parola che ha ispirato "codice threaded indiretta". Suona come la memorizzazione di un intero cancella quel po ', durante la memorizzazione di un puntatore imposta quel po'.

  

La moltiplicazione e la divisione dei tipi di dati puntatore sono vietate solo   dal compilatore. Nota: Sì, so che questo è assurdo. Ciò che voglio dire è   -? V'è il supporto hardware per proibire questo uso errato

Sì, alcuni componenti hardware non supporta direttamente questo tipo di operazioni.

Come altri hanno già detto, l'istruzione "moltiplica" nel 68000 e 6809 funzionano solo con (alcuni) "registri dati"; essi non possono essere applicati direttamente a valori "registri di indirizzo". (Sarebbe abbastanza facile per un compilatore per aggirare tali restrizioni - in MOV quei valori da un registro di indirizzo al registro dati appropriato, e quindi utilizzare MUL).

  

Tutti i valori di puntatore può essere colate a un unico tipo di dati?

Sì.

Al fine di memcpy () per lavorare a destra , i mandati C standard che ogni valore del puntatore di ogni genere può essere lanciato a un puntatore void ( "void *").

Il compilatore è tenuto a fare questo lavoro, anche per le architetture che utilizzano ancora i segmenti e gli offset.

  

Tutti i valori di puntatore può essere colate ad un singolo intero? In altre parole,   ciò architetture ancora fare uso di segmenti e compensazioni?

Non sono sicuro.

Ho il sospetto che tutti i valori puntatore può essere gettato al "size_t" e "ptrdiff_t" i tipi di dati integrali definiti in "<stddef.h>".

  

incrementando un puntatore è equivalente ad aggiungere sizeof (i dati appuntita   digitare) all'indirizzo memorizzato dal puntatore. Se p è un Int32 *   allora p + 1 è uguale all'indirizzo di memoria 4 byte dopo p.

Non è chiaro quello che chiedete qui.

D: Se ho un array di qualche tipo di struttura o operazione primitiva (per esempio, un "#include <stdint.h> ... int32_t example_array[1000]; ..."), e INCREMENTun puntatore che punta in tale matrice (ad esempio, "int32_t p = & example_array [99]; ... p ++; ..."), fa il puntatore ora puntare al successivo membro consecutivo di tale matrice, che è sizeof ( il tipo di dati a punta) byte più avanti nella memoria?

A: Sì, il compilatore deve fare il puntatore, dopo aver incrementato una volta, punto al successivo int32_t consecutivo indipendente nella matrice, sizeof (il tipo di dati a punta) byte più avanti nella memoria, in modo da essere conformi agli standard.

D: Quindi, se p è un Int32 *, allora p + 1 è uguale all'indirizzo di memoria 4 byte dopo p

A: Quando sizeof (int32_t) è in realtà pari a 4, sì. Altrimenti, come ad alcune macchine word-addressable inclusi alcuni DSP moderni dove sizeof (int32_t) può essere pari a 2 o addirittura 1, allora p + 1 è uguale all'indirizzo di memoria 2 o addirittura 1 "C byte" dopo p.

D: Quindi, se prendo il puntatore e lo gettò in un "int" ...

A:. Un tipo di "Tutto il mondo è un'eresia VAX"

D: ... e poi gettato che "int" di nuovo in un puntatore ...

A:. Un altro tipo di "Tutto il mondo è un'eresia VAX"

D: Quindi, se prendo il puntatore p che è un puntatore ad un int32_t, e la gettò in un certo tipo integrale che è abbastanza grande da contenere il puntatore, e quindi aggiungere sizeof( int32_t ) a quel tipo integrale, e poi più tardi fuso che tipo integrale di nuovo in un puntatore - quando faccio tutto questo, il puntatore risultante è uguale a p + 1

?

Non necessariamente.

Un sacco di DSP e un paio di altri chip moderni hanno word-oriented affrontare, piuttosto che l'elaborazione di byte-oriented utilizzato dai chip a 8 bit.

Alcuni dei compilatori C per tali chip stipare 2 caratteri in ogni parola, ma ci vuole 2 parole così tenere un'int32_t - in modo che riferiscono che sizeof( int32_t ) è 4. (Ho sentito voci che c'è un compilatore C per il 24 bit Motorola 56000 che fa questo).

Il compilatore è necessario per organizzare le cose in modo tale che fare "p ++" con un puntatore ad un int32_t incrementa il puntatore al successivo valore int32_t. Ci sono diversi modi per il compilatore per farlo.

Un modo conforme agli standard è quello di memorizzare ogni puntatore ad un int32_t come un "indirizzo parola indigena". Poiché prende 2 parole per contenere un singolo valore int32_t, il compilatore C compila "int32_t * p; ... p++" in un linguaggio assembly che incrementa il valore del puntatore di 2. D'altra parte, se si fa "int32_t * p; ... int x = (int)p; x += sizeof( int32_t ); p = (int32_t *)x;", che compilatore C per il 56000 è probabile compilarlo al linguaggio assembly che incrementa il valore del puntatore del 4.

  

Sono più utilizzato per puntatori essere utilizzati in una contigua, la memoria virtuale   spazio.

Diversi PIC e 8086 e altri sistemi hanno RAM non contigui - a pochi isolati di RAM a indirizzi che "hanno fatto l'hardware più semplice". Con I / O mappato in memoria o niente affatto attaccato alle lacune nello spazio di indirizzi tra i blocchi.

E 'ancora più scomodo di quanto sembri.

In alcuni casi - come ad esempio con la href="http://spin.atomicobject.com/2013/02/08/bit-banding/" rel="nofollow"> hardware utilizzato per evitare i problemi causati da lettura-modifica-scrivere - l'esatto stesso bit nella RAM può essere letto o scritto utilizzando 2 o più indirizzi diversi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top