Qual è la differenza tra una variabile e una posizione di memoria? [chiuso]


38

Recentemente ho cercato di spiegare i puntatori in modo visivo, come flashcard.

Domanda 001: questo è il disegno di una posizione nella memoria del computer. È vero che il suo indirizzo è 0x23452? Perché?

inserisci qui la descrizione dell'immagine

Risposta: Sì, perché 0x23452descrive dove il computer può trovare questa posizione.


Domanda 002: è vero che il personaggio bè memorizzato nella posizione di memoria 0x23452? Perché?

inserisci qui la descrizione dell'immagine

Risposta: No, perché il personaggio aè effettivamente memorizzato al suo interno.


Domanda 003: è vero che un puntatore è memorizzato nella posizione di memoria 0x23452? Perché?

inserisci qui la descrizione dell'immagine

Risposta: Sì, perché l'indirizzo della posizione della memoria 0x34501è memorizzato al suo interno.


Domanda 004: è vero che un puntatore è memorizzato nella posizione di memoria 0x23452? Perché?

inserisci qui la descrizione dell'immagine

Risposta: Sì, perché l'indirizzo di un'altra posizione di memoria è memorizzato al suo interno.


Ora per la parte che mi ha preoccupato. Un ingegnere del software mi ha spiegato i suggerimenti in questo modo:

Un puntatore è una variabile il cui valore è l'indirizzo di memoria di un'altra variabile.

Sulla base delle quattro flashcard che ho mostrato a tutti, definirei i puntatori in un modo leggermente diverso:

Un puntatore è una posizione di memoria il cui valore è l'indirizzo di memoria di un'altra posizione di memoria.

È sicuro dire che una variabile è la stessa cosa di una posizione di memoria?

Se no, allora chi ha ragione? Qual è la differenza tra una variabile e una posizione di memoria?


37
C'è un presupposto implicito che qui tutti la lettura di quelle immagini saprà il vostro intento che il numero esadecimale sotto la scatola è un indirizzo di memoria, e che la a, 0x23453. nilecc. roba al loro interno sono i valori. Potrebbe sembrare ovvio per te, ma non mi farebbe comodo dare risposte decisive a quelle domande senza vedere come sono definiti quei campi. Non c'è davvero modo di sapere se anella seconda immagine c'è un carattere, una stringa (se sono diversi) o il nome di una variabile. Se è una stringa, allora è nilanche una stringa? O un valore "nullo"?
ilkkachu,

39
La domanda 1 è una cattiva domanda. È qualcosa che devi dire ai lettori prima che possano rispondere alle altre domande. Invece di una domanda, dovrebbero essere le informazioni fornite al lettore: "Nelle seguenti domande, le caselle sono posizioni di memoria e i numeri esadecimali sotto sono i loro indirizzi".
17 del 26

15
Alla domanda 3 è impossibile rispondere dato il contesto. Non è possibile dire a livello di byte come il valore memorizzato in memoria viene interpretato / utilizzato a livello di applicazione.
17 del 26

6
Vale la pena notare: tutto ciò che stai scrivendo qui è vero per C o C ++ ma falso per praticamente qualsiasi linguaggio che non abbia riferimenti / dereferenze espliciti del puntatore. L'intera metafora delle variabili essendo slot in cui i valori vengono scomposti per un linguaggio (come Python, o Java, o C #, o Ruby, o JavaScript o molti altri) in cui l'assegnazione fa semplicemente un punto variabile a un oggetto senza copiarlo e le mutazioni all'oggetto sono visibili attraverso tutte le variabili che puntano ad esso. La documentazione di Python utilizza la metafora alternativa delle variabili come tag per gli oggetti appesi agli oggetti per questo motivo.
Mark Amery,

19
A proposito, e perdonami se lo capisci già, ma sembra che questo possa essere un punto di confusione: questa notazione "0x23452" è solo un modo per indicare un numero in formato esadecimale, ed è fatto solo per comodità. Ma è solo un numero: il prefisso 0x non indica in alcun modo che si tratta di un puntatore, ciò che è memorizzato in memoria è letteralmente solo un numero insignificante (è possibile etichettare le posizioni di memoria con interi decimali semplici). Il significato (ovvero come interpretare il numero) deriva dalla lingua: il tipo di variabile e il modo in cui viene utilizzato.
Filip Milovanović,

Risposte:


69

Una variabile è un costrutto logico che va all'intento di un algoritmo, mentre una posizione di memoria è un costrutto fisico che descrive il funzionamento di un computer. In generale, per eseguire un programma esiste una mappatura (generata dal compilatore) tra la nozione logica di una variabile e la memoria del computer.

(Anche nel linguaggio assembly abbiamo una nozione di variabili (logiche) che vanno all'algoritmo e all'intento e posizioni di memoria (fisica), sebbene siano più concentrate nell'assemblaggio.)

Una variabile è un concetto di alto livello (er). Una variabile rappresenta uno sconosciuto (come in matematica o un incarico di programmazione) o un segnaposto che può essere sostituito con un valore (come nella programmazione: parametri).

Una posizione di memoria è un concetto di basso livello (er). Una posizione di memoria può essere utilizzata per memorizzare un valore, a volte, per memorizzare il valore di una variabile. Tuttavia, un registro CPU è un altro modo per memorizzare il valore di alcune variabili. I registri della CPU sono anche posizioni di archiviazione di basso livello, ma non sono posizioni di memoria in quanto non hanno indirizzi, ma solo nomi.

In un certo senso, una variabile è un meccanismo di astrazione per esprimere l'intento del programma, mentre una posizione di memoria è un'entità fisica dell'ambiente di elaborazione che fornisce archiviazione e recupero.

Domanda 003: è vero che un puntatore è memorizzato nella posizione di memoria 0x23452? Perché?

Non possiamo dirlo per certo. Solo perché esiste un valore che funzionerebbe come indirizzo, non significa che sia quell'indirizzo, potrebbe invece essere l'intero (decimale) 144466. Non possiamo fare ipotesi sull'interpretazione dei valori semplicemente basandoci su come appaiono numericamente.

Domanda 004: è vero che un puntatore è memorizzato nella posizione di memoria 0x23452? Perché?

Questa è davvero una domanda strana. Si aspettano alcune ipotesi basate sulle caselle, tuttavia, notiamo che gli indirizzi aumentano di 1 per ogni casella. In qualsiasi computer moderno, ciò significherebbe che ogni casella può contenere un indirizzamento byte - byte è ormai la norma da decenni. Tuttavia un byte ha solo 8 bit e può variare da 0 a 255 (per valori senza segno); tuttavia mostrano un valore molto più grande memorizzato in uno di questi indirizzi, quindi molto sospetto. (Questo potrebbe funzionare se questa fosse una macchina indirizzata a parole, ma non lo dice, e oggi lo sono poche macchine, sebbene alcune macchine educative lo siano.)

Sulla base delle quattro flashcard che ho mostrato a tutti, definirei i puntatori in un modo leggermente diverso:

Un puntatore è una posizione di memoria il cui valore è l'indirizzo di memoria di un'altra posizione di memoria.

Mentre ci sono situazioni in cui questo pensiero è corretto, qui stai mescolando metafore. La nozione di una variabile va all'algoritmo e al suo intento: non è necessario supporre che tutte le variabili abbiano posizioni di memoria. Alcune variabili (in particolare gli array) hanno posizioni di memoria perché le posizioni di memoria supportano l'indirizzamento (mentre i registri della CPU possono solo essere nominati non indicizzati).

Per l'esecuzione, esiste una mappatura logica tra variabili e istruzioni, posizioni della memoria del processore e sequenze delle istruzioni del processore. Una variabile il cui valore non cambia mai (ad esempio una costante) non richiede nemmeno necessariamente una posizione di memoria, poiché il valore può essere riprodotto a piacimento (ad esempio, se necessario per le sequenze di codici generate dal compilatore).


4
E anche i byte a 8 bit non sono ancora universali.
Deduplicatore il

14
@JimmyJames Considerare il caso di un forindice di loop quando il compilatore decide di srotolare completamente il loop. In nessun punto del codice di output prodotto (sia esso un assembly o un codice macchina o un codice byte) c'è una posizione di memoria in cui viene memorizzato il contatore di loop. Ma è ancora una variabile.
dmckee,

4
@JimmyJames, Nel caso del puntatore a ciclo srotolato, quindi sì, se il tuo codice utilizza effettivamente il valore del contatore, allora deve essere caricato da qualche parte , ma (a) quel posto potrebbe essere un registro, e (b) in linea di principio non c'è motivo per cui dovrebbe essere la stessa posizione su ogni iterazione del ciclo non srotolato.
Solomon Slow

3
Se il loop sta facendo qualcosa di simile alla copia di array a lunghezza fissa sourcein array di uguale lunghezza, destun loop codificato for (int i=0; i<8; ++i) dest[i] = source[i];potrebbe benissimo essere compilato in qualcosa di equivalente alla ripetizione dell'apposito dest++ = source++;numero di volte. Con il contatore del ciclo stesso non è in nessun punto evidente (nemmeno nel registro) e solo il numero di ripetizioni ti dice la condizione del ciclo.
dmckee,

2
La distinzione è in qualche modo confusa da linguaggi come C la cui semantica è strettamente basata su un'astrazione di una macchina la cui memoria è costituita da posizioni numerate.
Michael Kay, il

20

È sicuro dire che una variabile è la stessa cosa di una posizione di memoria?

No. La variabile e la posizione della memoria sono due astrazioni a due diversi livelli di astrazione. Variabili e puntatori sono concetti di livello superiore a livello di codice / lingua, la posizione della memoria è un concetto di livello inferiore a livello di macchina. Una volta che un codice è stato compilato in un eseguibile, non ci sono più variabili. Cercare di parlare della posizione della memoria e delle variabili in questo modo è un errore categorico.

Una variabile può essere implementata usando la memoria, ma non sempre poiché un compilatore può ottimizzare un calcolo ed eseguire tutti i calcoli relativi a una variabile interamente nei registri, oppure può mettere una singola variabile in più posizioni di memoria oppure può utilizzare una singola memoria posizione per più variabili.

Un puntatore è una posizione di memoria il cui valore è l'indirizzo di memoria di un'altra posizione di memoria.

Questa serie di flashcard è così confusa, non solo non sono giusti, ma non sono nemmeno sbagliati.


1
Once a code had been compiled into an executable, there's no longer any variables.È qualcosa con cui probabilmente non sono d'accordo. È corretto che la tua variabile come la conosci (cioè con quel nome) non esiste più, ma il tuo fraseggio sembra suggerire che l'eseguibile compilato utilizza solo indirizzi di memoria. Non è corretto L'eseguibile compilato ma non in esecuzione non ha idea di quali indirizzi di memoria utilizzerà quando verrà eseguito. Il concetto di variabile (ovvero un riferimento riutilizzabile a qualsiasi indirizzo di memoria che verrà assegnato in fase di esecuzione) esiste ancora all'interno dell'eseguibile compilato.
Flater,

2
Oppure il compilatore potrebbe ottimizzare completamente la variabile, in vari modi. Pre-calcolo di qualcosa, potatura di variabili non necessarie. Se la variabile è una costante, il compilatore potrebbe finire per usare le istruzioni della CPU che usano le costanti, e direi che non conta più come variabile essendo ovunque.
Kutschkem,

16

Le variabili sono costrutti di linguaggio . Hanno un nome, risiedono in un ambito, possono essere referenziati da altre parti del codice, ecc. Sono un'entità logica . Il compilatore è libero di implementare questo costrutto linguistico nel modo che preferisce, purché il comportamento osservabile sia quello prescritto dallo standard linguistico. Pertanto, la variabile non deve nemmeno essere archiviata ovunque se il compilatore può dimostrare che non è necessario.

Le posizioni di memoria sono un concetto hardware . Indicano un posto nella memoria virtuale / fisica. Ogni posizione di memoria ha esattamente un indirizzo fisico e qualsiasi quantità di indirizzi virtuali che possono essere utilizzati per manipolarlo. Ma c'è sempre esattamente un byte memorizzato in ogni posizione di memoria.

I puntatori sono un tipo speciale di valori . Dire che qualcosa è un puntatore è come dire che qualcosa è di tipo double. Indica il numero di bit utilizzati per il valore e il modo in cui tali bit vengono interpretati, ma non significa che questo valore sia archiviato in una variabile, né che questo valore sia memorizzato.


Per fare un esempio in C: quando ho un array 2D int foo[6][7];e accedo a un elemento con esso foo[1][2], allora fooè una variabile che contiene un array. Quando fooviene utilizzato in questo contesto, viene trasformato in un puntatore al primo elemento dell'array. Questo puntatore non è memorizzato in nessuna variabile, né è archiviato in memoria, il suo valore viene generato solo all'interno di un registro della CPU, utilizzato e quindi dimenticato. Allo stesso modo, l'espressione foo[1]viene trasformata in un altro puntatore in questo contesto, che, ancora una volta, non si trova in una variabile, non viene archiviato in memoria, ma calcolato nella CPU, utilizzato e dimenticato. La variabile dei tre concetti , la posizione della memoria e il puntatore sono in realtà tre concetti diversi.


A proposito, intendevo davvero "c'è sempre esattamente un byte memorizzato in ogni posizione di memoria". Questo non era il caso nell'età della pietra del computer circa cinquant'anni fa, ma è vero praticamente per tutto l'hardware che è in uso oggi. Ogni volta che memorizzi un valore in memoria maggiore di un byte, stai effettivamente utilizzando un numero di posizioni di memoria consecutive. Vale a dire (supponendo un grande ordine di byte endian) il numero 0x01234567 è memorizzato come

+------+------+------+------+
| 0x01 | 0x23 | 0x45 | 0x67 |
+------+------+------+------+
    ^      ^      ^      ^
    |      |      |      |
 0x4242 0x4243 0x4244 0x4245

(Le macchine little endian come l'architettura X86 memorizzano i byte in ordine inverso.) Questo vale anche per i puntatori: un puntatore su una macchina a 64 bit è memorizzato in otto byte consecutivi, ognuno con il proprio indirizzo di memoria. Non puoi guardare una cella di memoria e dire: "Oh, questo è un puntatore!" Vedi sempre byte solo quando guardi la memoria .


Come fa il computer a sapere quando un gruppo di posizioni di memoria consecutive inizia e finisce?
progner

6
@progner Non lo fa. Essa interpreta i byte in memoria seguendo le istruzioni si arriva. Tali istruzioni sono anche memorizzate in nient'altro che una sequenza di byte stessi. Per la CPU l'unica differenza tra un byte che contiene un'istruzione, un byte che contiene un carattere e un byte che contiene alcuni bit in virgola mobile, è come è stato incaricato di utilizzare questo byte. Se il byte viene recuperato perché il contatore del programma punta ad esso, viene utilizzato come istruzione. Se viene recuperato perché un'istruzione dice di caricarlo in un registro float, viene utilizzato come dati a virgola mobile.
cmaster

7
@progner Questa è stata in realtà l'innovazione chiave dell'architettura von-Neuman: archiviare sia le istruzioni che i dati nella stessa memoria, consentendo alle istruzioni di modificare i dati che vengono successivamente eseguiti come ulteriori istruzioni. Ciò ha permesso il codice di auto-modifica, ma consente anche al kernel di un sistema di caricare alcuni programmi in memoria, e quindi dire alla CPU di eseguire quel programma. Prima di von-Neuman, computer come le macchine Zuse avrebbero ricevuto le loro istruzioni tramite un canale che era completamente indipendente dai dati su cui operavano.
cmaster

5

Vorrei concentrarmi sulla tua vera domanda: "chi ha ragione?" quando si confrontano queste due affermazioni:

  • Un puntatore è una variabile il cui valore è l'indirizzo di memoria di un'altra variabile
  • Un puntatore è una posizione di memoria il cui valore è l'indirizzo di memoria di un'altra posizione di memoria.

La risposta a questa è nessuna . Il primo parla di un "indirizzo di memoria di un'altra variabile", ma le variabili non hanno necessariamente indirizzi di memoria, come hanno già spiegato le altre risposte. Il secondo dice "un puntatore è una posizione di memoria", ma un puntatore è letteralmente solo un numero, che può essere memorizzato in una variabile, ma come prima, una variabile non ha necessariamente un indirizzo di memoria.

Alcuni esempi per dichiarazioni più precise:

  • "Un puntatore è un numero che rappresenta l'indirizzo di memoria di una posizione di memoria", oppure

  • "Una variabile puntatore è una variabile il cui valore è l'indirizzo di memoria di una posizione di memoria."

  • "Un indirizzo di memoria può contenere un puntatore che rappresenta l'indirizzo di memoria di una posizione di memoria."

Nota che a volte il termine "puntatore" viene utilizzato come scorciatoia per "variabile puntatore", il che va bene purché non crei confusione.


È possibile modificare "altro" in "a" perché un puntatore può puntare a se stesso.
Pieter B,

@PieterB: nitty, nitty ;-) non sono sicuro che questo lo renda davvero più chiaro, dal momento che volevo solo cambiare la formulazione originale nella misura necessaria per renderle sensate. Ma ahimè, ho fatto la modifica.
Doc Brown,

Per essere onesti, se ottieni quel nitpicky "ma un puntatore è letteralmente solo un numero" non è neanche corretto, in realtà un puntatore è un identificatore che fa riferimento a un numero;) O almeno dovevamo conoscere le specifiche della lingua per entrare in questi dettagli.
Zaibis,

2
Un puntatore è un valore (il numero è già troppo specifico per alcune implementazioni) potenzialmente riferito ad alcuni oggetti. Potenzialmente in quanto vi sono anche puntatori nulli, puntatori jolly e puntatori penzolanti, sebbene alcuni (o anche tutti!) Di questi possano essere esclusi dal linguaggio utilizzato.
Deduplicatore

2
@Deduplicatore: hai ragione, ma penso che il modello mentale di un puntatore come numero sia abbastanza buono ai fini di questa domanda. Quindi manteniamo le cose semplici.
Doc Brown,

5

Non direi certo che un puntatore è una posizione di memoria che contiene un indirizzo. Per uno, non sono a conoscenza di un'architettura in cui 0x23453potrebbe rientrare in un singolo byte. :) Anche se hai allontanato a mano la distinzione byte / parola, hai ancora il problema che ogni posizione di memoria contiene un indirizzo. Gli indirizzi sono solo numeri e il contenuto della memoria sono solo numeri.

Penso che il trucco qui sia che il "puntatore" descriva l'intento umano , non una caratteristica particolare dell'architettura. È simile al modo in cui un "carattere" o "stringa" non è una cosa concreta che puoi vedere nella memoria: anche questi sono solo numeri, ma funzionano come stringhe perché è così che vengono trattati. "Puntatore" significa semplicemente un valore destinato a essere utilizzato come indirizzo.

Onestamente, se il tuo obiettivo è insegnare una lingua particolare (Obiettivo C?), Non sono sicuro che disegnare il classico nastro di memoria sia anche così utile. Stai già dicendo bugie bianche mostrando valori digitati e valori troppo grandi per un byte. Insegnare alla semantica, non alla meccanica: l'intuizione chiave dei puntatori è che forniscono indiretta , che è uno strumento estremamente utile per capire.

Penso che un buon confronto potrebbe essere con un URL, che ti dice dove trovare alcuni dati, ma non sono i dati stessi. Ascoltami:

  • Raramente ti interessa quale sia effettivamente l'URL ; la stragrande maggioranza di loro viene eliminata in collegamenti con nomi. Molte persone usano Internet senza sapere esattamente come un URL risulta in una pagina; alcune persone dimenticano completamente gli URL.

  • Non ogni stringa è un URL o è destinata a essere utilizzata come URL.

  • Se si tenta di visitare un URL falso o una pagina che esisteva ma che è stata eliminata da allora, viene visualizzato un errore.

  • Un URL potrebbe puntare a un'immagine, del testo, della musica o di un numero qualsiasi di altri singoli elementi, oppure potrebbe puntare a una pagina con una varietà di cose contenute all'interno. È molto comune avere un sacco di pagine con layout simili ma dati diversi.

  • Se si crea una pagina Web e si desidera fare riferimento ai dati su un'altra pagina Web, non è necessario copiarla e incollarla; puoi semplicemente creare un link ad esso.

  • Qualsiasi numero di altre pagine può collegarsi allo stesso URL.

  • Se disponi di una raccolta di pagine simili, potresti creare una pagina indice che elenca i collegamenti a tutte, oppure potresti avere un collegamento "successivo" nella parte inferiore della pagina 1 che ti porta alla pagina 2 e così via. I vantaggi e gli svantaggi di entrambi gli approcci sono immediatamente evidenti, soprattutto se si considera ciò che il webmaster dovrebbe fare per aggiungere o rimuovere pagine in vari luoghi.

Questa analogia rende molto chiaro ciò che i puntatori sono per , che è fondamentale per la loro comprensione - altrimenti sembrano proprio loro arbitraria, complicato, e inutile. Capire come funziona qualcosa è molto più semplice se capisci già cosa fa e perché è utile. Se hai già interiorizzato che un puntatore è una scatola nera che ti dice dove si trova qualcos'altro, e poi impari a conoscere le complessità del modello di memoria, quindi rappresentare i puntatori come indirizzi è abbastanza ovvio. Inoltre, insegnare la semantica metterà i tuoi studenti in un posto molto migliore per comprendere e inventare altre forme di riferimento indiretto, il che è utile quando la maggior parte delle lingue principali non ha affatto indicazioni!


every memory location contains an address- Ogni posizione di memoria ha un indirizzo. Non è contenuto da nessuna parte, tranne forse in una variabile puntatore.
Robert Harvey,

@RobertHarvey ogni posizione di memoria (almeno una parola) contiene un numero, che può essere banalmente interpretato come un indirizzo. il punto era che nulla nell'hardware distingue effettivamente gli indirizzi dai non-indirizzi
Eevee

2

So che hai già accettato una risposta, e questa domanda ha già cinque risposte, ma c'è un punto che non menzionano, uno che penso ti abbia inciampato. I libri di testo di CS spesso cercano di essere agnostici riguardo alla scelta del linguaggio di programmazione, il che porta all'assunto implicito che la terminologia usata per descrivere le cose sia universale. Non lo è.

In C, l'operatore unaria e commerciale è chiamato operatore "indirizzo-di". I programmatori C non esiterebbero a dire che l'espressione &xrestituisce l'indirizzo della variabile x. Ovviamente significano "l'indirizzo di memoria in cui è memorizzato il valore della variabile x" ma nessuno è così pedante nelle conversazioni casuali. In C la parola "puntatore" di solito si riferisce al tipo di dati di una variabile destinata ad avere un indirizzo di memoria come valore. O equivalentemente il tipo di dati del valore. Ma alcune persone userebbero il "puntatore" come valore stesso.

In Java, tutte le variabili di tipo oggetto o array si comportano in modo molto simile ai puntatori C (ad eccezione dell'aritmetica dei puntatori), ma i programmatori Java li chiamano riferimenti, non puntatori.

C ++ considera riferimenti e puntatori come concetti diversi. Sono correlati, ma non sono la stessa cosa, quindi i programmatori C ++ devono fare la differenza nella conversazione. La e commerciale viene letta come "indirizzo di" in alcuni contesti e "riferimento a" in altri.

Un puntatore è una variabile il cui valore è l'indirizzo di memoria di un'altra variabile.

È così che un programmatore C potrebbe descriverlo, usando "un puntatore" nello stesso senso di "un int". (Come in "un puntatore contiene un indirizzo di memoria mentre un int contiene un numero intero entro un certo intervallo.")

Un puntatore è una posizione di memoria il cui valore è l'indirizzo di memoria di un'altra posizione di memoria.

È un modo strano di dirlo, perché richiede una definizione molto libera e informale di "è".

È sicuro dire che una variabile è la stessa cosa di una posizione di memoria?

Sarebbe più chiaro dire che un indirizzo di memoria è la posizione in memoria in cui è memorizzato il valore di una variabile. (Concesso, non tutte le variabili sono archiviate in memoria, a causa delle ottimizzazioni del compilatore, ma qualsiasi variabile il cui indirizzo è preso &xsarà.)


Dato che siamo pedanti: l'indirizzo in cui qualcosa è memorizzato. A parte un indirizzo che non è in grado di memorizzare nulla, spesso le cose vengono memorizzate in più posizioni adiacenti, solo una delle quali (generalmente selezionata da una regola in qualche modo coerente) viene indirizzata (e utilizzando solo uno di potenzialmente molti indirizzi).
Deduplicatore il

@Deduplicator Io per primo non sto cercando di essere pedante.
Gatkin,

Lo standard C distingue persino, formalmente, tra le variabili che devono seguire rigorosamente i passaggi della macchina astratta in ogni "punto di sequenza" - per motivi di sicurezza dei thread e alcune operazioni di basso livello su hardware mappato in memoria - e quelle che non " t, che sono liberi di essere spostati in un registro o completamente ottimizzati.
Davislor,

@Davislor: lo standard C usa il termine "oggetto" in luoghi in cui altre specifiche del linguaggio usano "variabile", oltre a descrivere altre cose che non sono variabili. Alcune discussioni possono usare il termine agnostico "variabile", ma per qualsiasi motivo allo Standard manca un termine per distinguere tra allocazioni disgiunte denominate (variabili) da altri tipi di oggetti come allocazioni nidificate (membri struttura / unione) o oggetti resi senza nome dereferenziando i puntatori. Informalmente, "variabile" è un ottimo termine, ma lo standard non lo utilizza.
supercat

@supercat Non è corretto. Lo standard C11 usa il termine "variabile" più di cento volte, di cui diverse dozzine sono sostantivi, ad esempio, "L'accesso simultaneo alla variabile che viene inizializzata, anche tramite un'operazione atomica, costituisce una corsa ai dati".
Davislor

1

L'istruzione Un puntatore è una variabile il cui valore è l'indirizzo di memoria di un'altra variabile è semplificata. Ma quando un lettore capirà cos'è esattamente una posizione di memoria e in che cosa differisce da una variabile, capirà già cos'è esattamente un puntatore e quindi non dovrà più fare affidamento su questa spiegazione inaccurata.

L'istruzione Un puntatore è una posizione di memoria il cui valore è l'indirizzo di memoria di un'altra posizione di memoria è errato. Il valore di un puntatore non deve essere archiviato in una posizione di memoria ed è discutibile se un puntatore deve puntare a una posizione di memoria, a seconda della definizione prevista di "memoria".

Qual è la differenza tra una variabile e una posizione di memoria

Una posizione di memoria è una delle molteplici posizioni possibili in cui è possibile archiviare i dati. Tali dati possono essere una variabile o parte di una variabile. Le variabili sono un modo per etichettare i dati.


0

Questa risposta si concentra su C e C ++; questo sembra appropriato poiché la tua domanda riguarda i puntatori che sono una parte più integrante di C / C ++ rispetto ad altre lingue. La maggior parte di questo post si applicherà alla maggior parte dei linguaggi compilati senza un tempo di esecuzione elaborato (come Pascal o Ada, ma non come Java o C #).

Le buone risposte già fornite sottolineano che una variabile è un costrutto linguistico a un livello più astratto della memoria fisica. Vorrei sottolineare, tuttavia, che questa astrazione ha una certa logica e sistema:

L'astrazione consiste principalmente nell'usare un nome anziché un indirizzo letterale.

L'idea di principio è che una variabile è un handle denominato per un oggetto tipizzato; gli oggetti in C / C ++ sono generalmente in memoria. Le lingue aggiungono quindi alcuni dettagli riguardanti la gestione della vita e il marshalling dei dati per le conversioni di tipo. Il concetto di variabili è più astratto degli indirizzi fisici perché in realtà non ci interessa il valore numerico degli indirizzi o l'esatta posizione delle funzioni nella memoria. Li chiamiamo semplicemente e in seguito li indirizziamo per nome, e il compilatore, il linker e il sistema di runtime si occupano dei dettagli grintosi.

E non pretendere che C / C ++ siano agnostici di memoria: dopo tutto, c'è l'operatore di indirizzo universalmente applicabile. Sì, vero, non puoi prendere l'indirizzo di una variabile C nella classe di memoria del registro; ma quando ne hai usato uno per ultimo? È un'eccezione speciale al concetto generale, non un rifiuto totale dell'argomento. La regola generale è, al contrario, che prendere un indirizzo di una variabile costringe effettivamente il compilatore a creare effettivamente un oggetto in memoria, anche se non lo farebbe altrimenti (ad es. Con costanti). Il concetto di "handle chiamato" è anche un buon paradigma per i riferimenti C ++: un riferimento è solo un altro nome per lo stesso oggetto.

Quando ho scritto un assemblatore inline per 68k è stato bello vedere come si potevano usare i nomi delle variabili come offset per indirizzare i registri (e si potevano usare i nomi delle variabili dichiarate registerinvece dei nomi dei registri bare metal!). Per il compilatore, una variabile è un offset di indirizzo costante. Per ripetere: le variabili sono denominate handle, in genere per gli oggetti in memoria.


I puntatori sono una parte fondamentale di C #, Java, JS e anche altre lingue. Chiamarli in modo diverso non cambia questo, sebbene sia un buon PR.
Deduplicatore il

@Deduplicatore :-) Buon vecchio Tony ...
Peter - Ripristina Monica il

0

Sembra che la domanda sia rivolta a un linguaggio popolare formato aumentando lo standard C con la garanzia aggiuntiva "Nei casi in cui alcune parti dello standard o la documentazione di un'implementazione descrivono il comportamento di qualche azione, e alcune altre parti lo categorizzano come indefinito , domina la prima parte ", nonché una definizione di" variabile "coerente con l'uso del termine da parte di altre lingue.

In quella lingua, ogni posizione di memoria può essere visualizzata come una cassetta postale numerata che contiene sempre un numero (tipicamente otto) di bit, ognuno dei quali può essere indipendentemente zero o uno. Le posizioni di memoria sono in genere organizzate in file di due, quattro o otto. e alcune operazioni vengono elaborate contemporaneamente su più posizioni di memoria consecutive. A seconda della macchina, alcune operazioni che operano su gruppi di due, quattro o otto posizioni di memoria potrebbero essere limitate al funzionamento su posizioni all'interno di una singola riga. Inoltre, mentre alcune macchine possono avere un'unica stanza di cassette postali numerate in sequenza, altre possono avere più gruppi disgiunti di cassette postali numerate.

Una variabile identifica un intervallo di posizioni di memoria associate esclusivamente ad essa e un tipo in base al quale tali posizioni di memoria devono essere interpretate. La lettura di una variabile comporterà l'interpretazione dei bit all'interno delle posizioni di memoria associate in modo appropriato al tipo di variabile e la scrittura di una variabile comporterà l'impostazione dei bit associati in modo adeguato al tipo e al valore.

Un indirizzo incapsula tutte le informazioni necessarie per identificare una cassetta postale. Questo può essere memorizzato come un numero semplice o come una sorta di designatore di gruppo insieme al numero di una cassetta postale all'interno di quel gruppo.

Applicando l' &operatore a una variabile si otterrà un puntatore che incapsula l'indirizzo e il suo tipo. Applicando l'unario *o l' []operatore a un puntatore, i bit di cassette postali che iniziano all'indirizzo incapsulato verranno interpretati o impostati in modo appropriato al tipo incapsulato.


Sembra che tu stia pensando troppo alla domanda.
Robert Harvey,

0

Sto arrivando tardi a questa festa, ma non posso resistere a inserire i miei 2 centesimi.

In questi momenti, qual è la differenza tra i valori memorizzati in queste posizioni di memoria?

Tempo 1

inserisci qui la descrizione dell'immagine

Tempo 2

inserisci qui la descrizione dell'immagine

Risposta corretta: niente. Sono tutti valori identici presentati con diverse interpretazioni del loro significato.

Come lo so? Perché sono io quello che l'ha inventato. Non lo sai ancora davvero.

Stai incontrando qualcosa che io chiamo il problema fuori banda . Come interpretare correttamente il significato di questi valori non è memorizzato qui. Quella conoscenza è immagazzinata altrove. Tuttavia, quando presenti questi valori sulla carta, inserisci questa interpretazione. Ciò significa che hai aggiunto informazioni che semplicemente non esistono in queste posizioni di memoria.

Ad esempio, i valori qui sono identici, ma sai che è vero solo se hai ragione quando assumi un ASCII codifica di caratteri / UTF-8 è come ho ottenuto il primo, piuttosto che dire EBCDIC . E devi anche supporre che il secondo sia espressioni esadecimali dei valori numerici memorizzati in quelle posizioni di memoria, che potrebbero essere tutti puntatori ad altri indirizzi, piuttosto che dire riferimenti a stringhe che iniziano tutte con "0x". : P

Nulla di ciò che è memorizzato in queste posizioni di memoria indica che nessuna di queste ipotesi sia corretta. Tali informazioni possono essere archiviate. Ma sarebbe memorizzato altrove.

Questo è il problema di presentazione . Non è possibile esprimere alcun numero senza prima concordare su come presentarlo. Puoi fare affidamento su ipotesi, convenzioni e contesto, ma se lo gratti profondamente, quando la presentazione non è definita in modo esplicito, l'unica risposta veramente corretta è "informazioni insufficienti".


È ancora più divertente quando la stessa memoria viene utilizzata per diverse cose costanti allo stesso tempo.
Deduplicatore

@Deduplicator True. Questo mi fa sempre pensare al cast reinterpretare di c ++ . Gli stessi pezzi visti in un modo diverso.
candied_orange

@Deduplicator o, vieni a pensarci bene, unione in c
candied_orange
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.