Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Puntatori in informatica, Appunti di Programmazione C

Il documento spiega il concetto di puntatori in informatica, ovvero gli indirizzi di dati che permettono di accedere a strutture dati complesse in modo semplice e compatto. Vengono descritte le dichiarazioni dei puntatori, gli operatori specifici per i puntatori e come utilizzarli come argomenti di funzioni. Viene inoltre spiegato come i puntatori possono puntare ad elementi di un array e come sommare o sottrarre un intero a un puntatore per ottenere l'indirizzo di una componente di un array.

Tipologia: Appunti

2020/2021

In vendita dal 28/03/2022

Acaiazza
Acaiazza 🇮🇹

8 documenti

1 / 15

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Puntatori
Ogni dato presente in memoria possiede un indirizzo: i puntatori sono indirizzi di dati, nonché dati essi
stessi.
Ogni variabile occupa una o più locazioni di memoria (byte); l’indirizzo del primo byte che viene usato per
rappresentare la variabile è anche l’indirizzo della variabile. Gli indirizzi delle locazioni di memoria possono
essere memorizzate in variabili speciali dette puntatori e, quando memorizziamo l’indirizzo di una variabile
i nel puntatore p, diciamo che p “punta a” i.
I puntatori permettono di accedere a strutture dati anche complesse in modo semplice e compatto;
consentono la condivisione di dati fra diverse parti dei programmi (passaggio di parametri per riferimento);
consentono di allocare dinamicamente la memoria e di definire strutture dinamiche; permettono di creare
connessioni fra dati: strutture a puntatori.
Dichirazione dei puntatori:
Quando una variabile puntatore viene dichiarata, il suo nome deve essere preceduto da un asterisco:
𝑖𝑛𝑡 𝑝;
p è una variabile che può contenere l’indirizzo di un oggetto (variabile) di tipo int.
Usiamo il termine oggetto al posto di variabile in quanto p potrebbe puntare ad una zona di memoria che
non appartiene ad una variabile.
Variabili puntatore possono apparire insieme ad altre variabili nella dichiarazione:
𝑖𝑛𝑡 𝑖, 𝑗, 𝑎[10], 𝑏[20],∗ 𝑝,∗ 𝑞;
Il C richiede che ogni puntatore punti solo ad oggetti del tipo specificato nella dichiarazione (detto il tipo
referenziato dal puntatore):
𝑖𝑛𝑡 𝑝; /∗ 𝑝𝑜𝑖𝑛𝑡𝑠 𝑜𝑛𝑙𝑦 𝑡𝑜 𝑖𝑛𝑡𝑒𝑔𝑒𝑟𝑠 ∗/
𝑑𝑜𝑢𝑏𝑙𝑒 𝑞; /∗ 𝑝𝑜𝑖𝑛𝑡𝑠 𝑜𝑛𝑙𝑦 𝑡𝑜 𝑑𝑜𝑢𝑏𝑙𝑒𝑠 ∗/
𝑐ℎ𝑎𝑟 𝑟; /∗ 𝑝𝑜𝑖𝑛𝑡𝑠 𝑜𝑛𝑙𝑦 𝑡𝑜 𝑐ℎ𝑎𝑟𝑎𝑐𝑡𝑒𝑟𝑠 ∗/
Il tipo referenziato può essere qualsiasi tipo.
Il C fornisce una coppia di operatori specifici per i puntatori:
1. Per sapere l’indirizzo di una variabile si può esare l’operatore indirizzo &;
2. Per accedere all’oggetto puntato da un puntatore si può utilizzare l’operatore ridirezione *;
(l’asterisco della dichiarazione NON è un operatore di ridirezione).
La dichiarazione di una variabile puntatore crea la variabile puntatore senza che essa punti ad un oggetto
𝑖𝑛𝑡 𝑝; /∗ 𝑝𝑜𝑖𝑛𝑡𝑠 𝑛𝑜𝑤ℎ𝑒𝑟𝑒 𝑖𝑛 𝑝𝑎𝑟𝑡𝑖𝑐𝑢𝑙𝑎𝑟 ∗/
Per utilizzare il puntatore p dobbiamo prima assegnargli un valore
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Anteprima parziale del testo

Scarica Puntatori in informatica e più Appunti in PDF di Programmazione C solo su Docsity!

Puntatori

Ogni dato presente in memoria possiede un indirizzo: i puntatori sono indirizzi di dati, nonché dati essi

stessi.

Ogni variabile occupa una o più locazioni di memoria (byte); l’indirizzo del primo byte che viene usato per

rappresentare la variabile è anche l’indirizzo della variabile. Gli indirizzi delle locazioni di memoria possono

essere memorizzate in variabili speciali dette puntatori e, quando memorizziamo l’indirizzo di una variabile

i nel puntatore p, diciamo che p “punta a” i.

I puntatori permettono di accedere a strutture dati anche complesse in modo semplice e compatto;

consentono la condivisione di dati fra diverse parti dei programmi (passaggio di parametri per riferimento);

consentono di allocare dinamicamente la memoria e di definire strutture dinamiche; permettono di creare

connessioni fra dati: strutture a puntatori.

 Dichirazione dei puntatori:

Quando una variabile puntatore viene dichiarata, il suo nome deve essere preceduto da un asterisco:

p è una variabile che può contenere l’indirizzo di un oggetto (variabile) di tipo int.

Usiamo il termine oggetto al posto di variabile in quanto p potrebbe puntare ad una zona di memoria che

non appartiene ad una variabile.

Variabili puntatore possono apparire insieme ad altre variabili nella dichiarazione:

𝑖𝑛𝑡 𝑖, 𝑗, 𝑎[ 10 ], 𝑏[ 20 ],∗ 𝑝,∗ 𝑞;

Il C richiede che ogni puntatore punti solo ad oggetti del tipo specificato nella dichiarazione (detto il tipo

referenziato dal puntatore):

Il tipo referenziato può essere qualsiasi tipo.

Il C fornisce una coppia di operatori specifici per i puntatori:

  1. Per sapere l’indirizzo di una variabile si può esare l’operatore indirizzo &;
  2. Per accedere all’oggetto puntato da un puntatore si può utilizzare l’operatore ridirezione *;

(l’asterisco della dichiarazione NON è un operatore di ridirezione).

La dichiarazione di una variabile puntatore crea la variabile puntatore senza che essa punti ad un oggetto

Per utilizzare il puntatore p dobbiamo prima assegnargli un valore

Un modo per assegnare un indirizzo ad un puntatore sfrutta l’operatore indirizzo:

Assegnare a p l’indirizzo di i significa far puntare p ad i.

È possibile inizializzare un puntatore nel momento della dichiarazione:

La dichiarazione di i può essere combinata con quella di p:

Una volta che un puntatore punta ad un oggetto è possibile usare l’operatore ridirezione * per accedere a

ciò che è memorizzato nell’oggetto. Se p punta ad i, possiamo stampare il valore di i in questo modo:

𝑝𝑟𝑖𝑛𝑡𝑓("%𝑑\𝑛",∗ 𝑝);

Applicando & ad una variabile si ottiene l’indirizzo della variabile; applicando * ad un puntatore si ottiene il

valore della variabile:

Quando p punta ad i, *p è un sinonimo (alias) di i, cioè: *p ha lo stesso valore di i, quindi cambiando il

valore di *p si cambia il valore i.

 Puntatori come argomenti:

In generale, una funzione non può modificare i suoi argomenti, perché gli argomenti vengono passati per

valore. Se però passiamo un puntatore alla variabile invece della variabile, allora sarà il puntatore ad essere

passato per valore, ma grazie al puntatore potremo modificare la variabile.

𝑚𝑎𝑥_𝑚𝑖𝑛(𝑏, 𝑁, &𝑏𝑖𝑔, &𝑠𝑚𝑎𝑙𝑙);

𝑝𝑟𝑖𝑛𝑡𝑓("𝐿𝑎𝑟𝑔𝑒𝑠𝑡: %𝑑\𝑛", 𝑏𝑖𝑔);

𝑝𝑟𝑖𝑛𝑡𝑓("𝑆𝑚𝑎𝑙𝑙𝑒𝑠𝑡: %𝑑\𝑛", 𝑠𝑚𝑎𝑙𝑙);

𝑣𝑜𝑖𝑑 𝑚𝑎𝑥_𝑚𝑖𝑛(𝑖𝑛𝑡 𝑎[], 𝑖𝑛𝑡 𝑛, 𝑖𝑛𝑡 ∗ 𝑚𝑎𝑥, 𝑖𝑛𝑡 ∗ 𝑚𝑖𝑛)

∗ 𝑚𝑎𝑥 = ∗ 𝑚𝑖𝑛 = 𝑎[ 0 ];

𝑖𝑓 (𝑎[𝑖] > ∗ 𝑚𝑎𝑥)

∗ 𝑚𝑎𝑥 = 𝑎[𝑖];

𝑒𝑙𝑠𝑒 𝑖𝑓 (𝑎[𝑖] < ∗ 𝑚𝑖𝑛)

∗ 𝑚𝑖𝑛 = 𝑎[𝑖];

 Puntatori come valore di ritorno:

Una funzione può restituire un puntatore:

Ecco una chiamata alla funzione max:

Dopo la chiamata, p punta o ad i oppure a j. La funzione max restituisce uno dei due puntatori che sono

stati forniti come argomenti.

Una funizone può restiture anche un puntatore ad altre variabili (una variabile globale o una variabile

statica). Attenzione a non restituire un puntatore ad una variabile locale:

La variabile i non esisterà quando f termina. Un puntatore può puntare ad elementi di un array: se a è un

array, &a[i] è un puntatore all’elemento i di a.

A volte è utile che una funzione restituisca il puntatore ad un elemento di un array. Ecco una funzione che

restituisce un puntatore all’elemento centrale dell’array a, assumendo che a abbia n elementi:

𝑖𝑛𝑡 ∗ 𝑓𝑖𝑛𝑑_𝑚𝑖𝑑𝑑𝑙𝑒(𝑖𝑛𝑡 𝑎[], 𝑖𝑛𝑡 𝑛)

𝑟𝑒𝑡𝑢𝑟𝑛 &𝑎[𝑛/ 2 ];

Se p è il puntatore all’elemento iniziale di un array A, e k è un intero, allora p + k è per definizione l’indirizzo

della componente k di A, cioè &A[k].

Quando si somma un intero k a un puntatore p, si ottiene l’indirizzo che avrebbe la componente di indice k

di un array allocato all’indirizzo p. E’ anche possibile sottrarre un intero da un puntatore, col significato

inverso.

 Aritmetica dei puntatori:

Il C permette di eseguire addizioni e sottrazioni con i puntatori. Questo permette di gestire gli array usando

i puntatori al posto degli indici. L’interconnessione fra puntatori ed array in C è molto stretta: capire questa

interconnessione è di fondamentale importanza per la programmazione in C.

Abbiamo visto che un puntatore può puntare a elementi di un array:

𝑖𝑛𝑡 𝑎[ 10 ],∗ 𝑝;

𝑝 = &𝑎[ 0 ];

possiamo accedere ad a[0] usando p; per esempio possiamo memorizzare il valore 5 in a[0] scrivendo

Se p punta ad un elemento di un array a, è possibile accedere agli altri elementi di a usando un’operazione

aritmetica su p. Si possono effettuare queste (e solo queste) operazioni aritmetiche sui puntatori:

  1. Addizionare un intero ad un puntatore;
  2. Sottrarre un intero da un puntatore;
  3. Sottrarre un puntatore da un altro puntatore.
  4. Sommare un intero j ad un puntatore p fa si che il puntatore punti all’elemento che si trova j

posizioni dopo l’elemento attualmente puntato da p. Più precisamente, se p punta all’elemento

a[i], allora p + j punta all’elemento a[i+j]. Si assuma di aver fatto le seguenti dichiarazione:

equivalente all’espressione (a + i), quindi, &a[i][0] è equivalente a &((a[i] + 0)), che è equivalente a

&*a[i], e quest’ultima espressione è uguale a a[i], poiché gli operatori & * si cancellano.

Stringhe

Esistono due tipi di stringhe: le stringhe costanti (o letterali, per usare il gergo del C) e le stringhe variabili

(cioè variabili il cui valore è una stringa).

Le stringhe sono array di caratteri; un carattere speciale—il carattere nullo—segnala la fine della stringa.

La libreria standard del C fornisce molte funzioni per manipolare le stringhe.

 Stringhe letterali:

Una stringa letterale è una sequenza di caratteri racchiusi fra doppi apici; le stringhe letterali possono

anche contenere sequenze di escape.

Tali sequenze vengono usate spesso nelle stringhe di formato per printf e scanf.

Quando il compilatore trova una stringa letterale di lunghezza n, alloca n + 1 byte di memoria per la stringa.

Tale memoria conterrà gli n caratteri della stringa più un carattere aggiuntivo—il carattere nullo—che

segnala la fine della stringa. Il carattere nullo ha codice ASCII 0 ed è rappresentato dalla sequenza di escape

\ 0.

Poiché una stringa è memorizzata in un array di caratteri, il compilatore la vede come char *. Sia printf che

scanf si aspettano valori di tipo char * per il primo argomento.

La seguente chiamata a printf passa l’indirizzo di "abc" (un puntatore alla locazione di memoria dove è

memorizzato il carattere a):

Possiamo usare una stringa letterale dovunque sia permesso usare un char *. È possibile usare un indice:

𝑐ℎ = "𝑎𝑏𝑐"[ 1 ];

Il valore di ch sarà il carattere b.

Non è possibile modificare una stringa letterale: un programma che cerca di cambiare una stringa letterale

può andare in crash o avere comportamenti non definiti.

Una stringa letterale che contiene un solo carattere è diversa da una costante “carattere”

  • "a" è rappresentata da un puntatore;
  • 'a' è rappresentata da un intero.

 Stringhe variabili:

Un array monodimensionale di caratteri può essere usato per memorizzare una stringa: una stringa deve

essere terminata dal carattere nullo. Le difficoltà di questo approccio sono:

  • Può essere difficile dire se un array di caratteri viene utilizzato come stringa;
  • Le funzioni per le stringhe devono manipolare con attenzione il carattere (nullo) di fine stringa;
  • Misurare la lunghezza di una stringa significa cercare il carattere nullo che ne indica la fine.

Se una stringa può essere lunga 80 caratteri, deve essere dichiarata come array di 81 elementi:

#𝑑𝑒𝑓𝑖𝑛𝑒 𝑆𝑇𝑅_𝐿𝐸𝑁 80

𝑐ℎ𝑎𝑟 𝑠𝑡𝑟[𝑆𝑇𝑅_𝐿𝐸𝑁 + 1 ];

La locazione aggiuntiva serve per il carattere di fine stringa. Usare una macro che definisce la lunghezza

della stringa e poi aggiungere il +1 nella dichiarazione è una pratica comune.

Ricordarsi del carattere di fine stringa nella dichiarazione di una stringa variabile. Dimenticarsi di farlo può

creare problemi.

La dimensione dell’array non è la lunghezza della stringa e la lunghezza della stringa dipende dalla posizione

nell’array del carattere di fine stringa. Un array di lunghezza STR_LEN + 1 può contenere stringhe di

lunghezza fra 0 e STR_LEN.

Una stringa variabile può essere inizializzata al momento della dichiarazione; esempio:

𝑐ℎ𝑎𝑟 𝑑𝑎𝑡𝑒 1 [ 8 ] = "𝐽𝑢𝑛𝑒 14";

Il compilatore allocherà automaticamente 8 byte per l’array ed inserirà il carattere di fine stringa. In questo

contesto,"June 14" non è una stringa letterale ma un’abbreviazione dell’inizializzatore per l’array. Se

l’inizializzatore ha meno caratteri della grandezza dell’array, il compilatore riempie il resto con caratteri

nulli.

La dichiarazione 𝑐ℎ𝑎𝑟 𝑑𝑎𝑡𝑒[] = "𝐽𝑢𝑛𝑒 14"; dichiara date come un array; la dichiarazione 𝑐ℎ𝑎𝑟 ∗ 𝑑𝑎𝑡𝑒 =

"𝐽𝑢𝑛𝑒 14"; dichiara date come un puntatore. Entrambe le variabili possono essere usate come stringhe,

poiché array e puntatori sono in stretta relazione.

Tuttavia ci sono differenze importanti fra le due versioni della variabile date: nella versione “array”, i

caratteri memorizzati nella variabile date possono essere modificati e “date” è il nome dell’array; nella

versione “puntatore”, date punta ad una stringa letterale che non può essere modificata e “date” è una

variabile che punta ad una stringa.

La dichiarazione 𝑐ℎ𝑎𝑟 ∗ 𝑝; non alloca memoria. Prima di poter usare p come una stringa, dobbiamo farla

puntare ad un array: una possibilità è quella di farla puntare ad una stringa variabile:

[

𝐿𝐸𝑁

]

Un’altra possibilità è quella di allocare dinamicamente la memoria necessaria.

Usare un puntatore non inizializzato può avere conseguenze disastrose: poiché la variabile p non è stata

inizializzata il comportamento del programma non è definito.

 Leggere e scrivere stringhe:

Una stringa può essere stampata usando printf o puts.

Leggere una stringa è un po’ più complicato perché l’input potrebbe essere più lungo della lunghezza

dell’array dove la stringa verrà memorizzata; per leggere una stringa intera possiamo usare scanf o gets,

oppure possiamo leggere un carattere alla volta.

La specifica di conversione %s permette di usare una stringa con printf :

𝑐ℎ𝑎𝑟 𝑠𝑡𝑟[ ] = “𝐴𝑟𝑒 𝑤𝑒 ℎ𝑎𝑣𝑖𝑛𝑔 𝑓𝑢𝑛 𝑦𝑒𝑡? ”;

𝑝 𝑟𝑖𝑛𝑡𝑓("%𝑠\𝑛", 𝑠𝑡𝑟);

Questa istruzione confronta str1 e str2 come puntatori: poiché str1 e str2 puntano ad indirizzi diversi,

l’espressione str1 == str2 avrà valore 0.

La libreria C fornisce un ricco insieme di funzioni per operare sulle stringhe. I programmi che vogliono

utilizzare le funzioni della libreria devono includere il file string.h:

Negli esempi che seguono assumeremo che str1 e str2 siano array di caratteri usati come stringhe.

  1. La funzione strcpy (string copy): il suo prototipo è

strcpy copia la stringa s2 nella stringa s1.

Per essere precisi dovremmo dire “strcpy copia la stringa puntata da s2 nell’array puntato da s1.”

Strcpy restituisce il valore di s1 (un puntatore alla stringa di destinazione).

Nella chiamata strcpy(str1, str2), strcpy non ha modo di controllare che ci sia abbastanza spazio per

copiare str2 nell’array puntato da str1: se non c’è abbastanza spazio il comportamento del

programma non è definite.

  1. La funzione strncpy (string copy sicura): usare la funzione strncpy è più sicuro, anche se più lento.

Ha un terzo argomento che specifica la grandezza dell’array di destinazione. Una chiamata strncpy

che copia str2 in str1:

strncpy non scriverà il carattere nullo alla fine di str1 se la lunghezza di str2 è maggiore della

lunghezza dell’array str1. Ecco come ovviare al problema:

𝑠𝑡𝑟 1 [𝑠𝑖𝑧𝑒𝑜𝑓(𝑠𝑡𝑟 1 ) − 1 ] = ′\0′;

L’istruzione dopo la chiamata alla funzione scrive in modo esplicito il carattere nullo nell’ultima

posizione dell’array str.

  1. La funzione strlen (string lenght): il suo prototipo è:

𝑠𝑖𝑧𝑒_𝑡 𝑠𝑡𝑟𝑙𝑒𝑛(𝑐𝑜𝑛𝑠𝑡 𝑐ℎ𝑎𝑟 ∗ 𝑠);

dove size_t è un nome typedef che rappresenta un intero senza segno. Strlen restituisce la

lunghezza della stringa s, senza contare il carattere nullo di fine stringa.

  1. La funzione strcat (concatenation): il suo prototipo è:

strcat aggiunge il contenuto della stringa s2 alla (fine della) stringa s1; restituisce un il valore di s1 (il

puntatore alla stringa risultato della concatenazione).

Il comportamento del programma non è definito se strcat(str1, str2) non ha abbastanza spazio in

str1 per inserire anche i caratteri di str2.

  1. La funzione strncat è più sicura, anche se più lenta. Come strncpy, ha un terzo parametro che

specifica il numero massimo di caratteri che può copiare.

Ecco una chiamata a strncat:

strncat terminerà str1 con un carattere nullo, che dobbiamo considerare quando calcoliamo il terzo

argomento.

  1. La funzione strcmp (string comparison): prototipo:

strcmp confronta la stringa s1 con s2, e restituisce un valore :

  • minore di 0 se s1 è (lessicograficamente) minore di s2;
  • uguale a 0, se s1 è uguale a s2;
  • maggiore di 0, se s1 è (lessicograficamente) maggiore di s2.

Usando il giusto operatore (<, <=, >, >=, ==, !=), possiamo controllare tutte le relazioni fra str1 e

str2.

strcmp considera l’ordine lessicografico: s1 è minore di s2 se una delle seguenti condizioni è

soddisfatta: i primi i caratteri di s1 e s2 sono uguali, ma il carattere (i+1)-esimo di s1 è minore

del carattere (i+1)-esimo di s2.

Tutti i caratterei di s1 sono uguali a quelli di s2, ma s1 è più corta di s2.

La relazione di ‘<’ fra caratteri è determinta dal codice ASCII del carattere. Nella codifica ASCII

A–Z, a–z, e 0–9 hanno codici consecutivi

• ‘A’=65, ‘Z’=

  • ‘a’=97 ‘z’=
  • Le lettere maiuscole sono ‘<’ delle lettere minuscule;
  • Le cifre sono ‘<’ delle lettere ;
  • Lo spazio (codice 32) è ‘<’ di tutti i caratteri stampabili;
  1. Ecco una versione di strlen che cerca la fine di una stringa usando una variabile che tiene traccia

della lunghezza della stringa:

𝑠𝑖𝑧𝑒_𝑡 𝑠𝑡𝑟𝑙𝑒𝑛(𝑐𝑜𝑛𝑠𝑡 𝑐ℎ𝑎𝑟 ∗ 𝑠)

𝑠𝑖𝑧𝑒_𝑡 𝑛;

𝑓𝑜𝑟 (𝑛 = 0 ; ∗ 𝑠! = ′\0′; 𝑠 + +)

 Copiare una stringa:

La copia di una stringa è un’operazione molto comune. Per vedere i modi tipici in cui si copia una stringa in

C, svilupperemo due versioni della funzione strcat, la prima versione di strcat (prossima slide) opera nel

seguente modo: trova il carattere nullo di fine stringa nella prima stringa s1 e fa puntare p ad esso e poi

copia i caratteri di s2 scrivendoli a partire dal punto in cui punta p.

  • Copia della nuova stringa nella posizione ordinata; chiamata a strcat per aggiungere il

promemoria al giorno;

Una complicazione: giustificare a destra il numero del giorno in un campo di 2 caratteri. Una soluzione:

usare scanf per leggere il giorno in una variabile di tipo int e poi usare sprintf per riconvertirla in una stringa

sprintf è simile a printf, ma al posto di stampare scrive il risultato in una stringa. La chiamata

𝑠𝑝𝑟𝑖𝑛𝑡𝑓(𝑑𝑎𝑦_𝑠𝑡𝑟, "%2𝑑", 𝑑𝑎𝑦); scrive il valore di day in day_str.

La seguente chiamata a scanf assicura che non ci siano più di 2 cifre nel giorno dato in input:

 Array di stringhe:

Esistono vari modi per memorizzare un array di stringhe. Una possibilità è quella di usare un array bi-

dimensionale, e memorizzare una stringa in ogni riga

𝑐ℎ𝑎𝑟 𝑝𝑙𝑎𝑛𝑒𝑡𝑠[][ 8 ]

Il numero di righe nell’array può essere omesso, ma occorre specificare il numero di colonne.

L’array planets contiene vari byte non utilizzati:

Spesso quando dobbiamo gestire molte stringhe ci troveremo in questa situazione: alcune stringhe più

lunghe altre più corte.

Potremmo usare un array irregolare (ragged array) in cui le righe possono avere lunghezze diverse, oppure

possiamo “simulare” un tale array utilizzando un array di puntatori alle stringhe:

𝑐ℎ𝑎𝑟 ∗ 𝑝𝑙𝑎𝑛𝑒𝑡𝑠[]

Ecco come verranno memorizzate le stringhe planets:

Per accedere ad una delle stringhe dobbiamo usare l’indice per selezionare il puntatore dell’array planets.

Dopo di che possiamo accedere ai caratteri della stringa come si fa con un normale array bidimensionale.

Ecco un ciclo che cerca le stringhe che iniziano per M: