2012-08-31 40 views
9

Sono confuso circa la seguente riga di codice:Array di puntatori a char array

char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 

Il modo comprendo, ogni parola viene prima memorizzato e poi ogni posizione dell'array words punterà quindi alla prima carattere di ogni parola. Come vengono memorizzate queste stringhe? C'è allocazione dinamica in corso qui o queste parole sono memorizzate nello stack?

Se sono memorizzati nello stack, in che modo vengono memorizzati? Per esempio, se stampo alcuni dei contenuti di words come di seguito:

#include <stdio.h> 
int main() { 
    char* words[] = { "aaa", "bbbb", "ccccc", "dddddd" }; 
    printf("\n\n(*words)[0] = %s", words[0]); 
    printf("\n\n(*words)[0]+1 = %s", words[0]+1); 
    return 0; 
} 

invece di stampare aaa e bbbb, quello che ottengo è aaa e aa. Non capisco davvero quale sia la ragione per questo poiché, per come la vedo io, words[0]+1 dovrei puntare alla stringa bbbb e non al secondo carattere di aaa. Che cosa sta succedendo qui?

+0

Siete confusi 'parole [0] + 1',' (parole + 1) [0] 'e' parole [1] '? –

+0

Prova '& words [0] + 1' – oldrinb

risposta

2

il modo di vedere, parole [0] +1 dovrebbero indicare l'bbbb stringa e non sul secondo carattere di aaa

No. words[0] è un puntatore char sé - è perfettamente bene che ottieni il secondo carattere di "aaa" aggiungendone uno. Quello che vuoi è words + 1 o &words[0] + 1 che sarà correttamente "bbbb".

Inoltre, le stringhe vengono allocate all'avvio dell'eseguibile e probabilmente vengono inserite nella sezione data o bss del file binario dal linker. Inoltre, quando dichiari e inizializzi words, verrà assegnato nello stack come qualsiasi altro array automatico e i relativi elementi verranno assegnati ai puntatori all'inizio di ogni costante di stringa.

+0

Capisco. Ho effettivamente provato a fare cose come 'words [1] [1] = 'u'' per cambiare' bbbb' in 'bubb', ma' bbbb' rimane lo stesso dopo averlo modificato (!). È così perché le stringhe sono di sola lettura (presumo che lo siano poiché sono valori validi)? –

+0

@curvature si lo sono. Sii contento che non sia andato in crash: la modifica delle costanti di stringa è UB. –

3

parole [0] indicano il primo 'a' in "aaa".

parole [0] +1 sposta quel puntatore lungo un carattere, quindi viene puntato sul secondo "a".

parole [1] punti a "bbbb"

parole [1] +1 punti "bbb", ad esempio la seconda 'b' in "bbbb".

0

parole [0] restituisce l'indirizzo di aaa. Aggiungendo 1 a quello si aumenta l'indirizzo per puntare al secondo a.

Intendi dire parole [0 + 1]?

Questo dovrebbe darti quello che ti aspetti.

0

Tutte le 4 stringhe hanno durata di memorizzazione statica e vengono assegnate prima dell'avvio del programma.

Nell'inizializzatore, gli array vengono convertiti in puntatori a char e l'array words viene inizializzato con i valori del puntatore.

1

Le stringhe letterali sono memorizzate nella memoria statica. La loro posizione effettiva dipende dall'implementazione, ma le stringhe letterali vengono memorizzate da qualche parte su, in genere nella porzione di dati dell'eseguibile - questa non è né dinamica né allocazione di stack. L'array quindi contiene i puntatori a queste posizioni.

parole [0] +1 dovrebbero puntare alla stringa bbbb e non al secondo carattere di aaa.

Questo semplicemente non è il modo in cui l'indicizzazione di array funziona. Si indicizza l'array di stringhe con words[0], ora si dispone di una stringa e qualsiasi operazione si applica a quella stringa. Non puoi fare aritmetica con indici di array al di fuori del pedice. Per ottenere la stringa "bbbb", si utilizzerà words[1].

6

La differenza è perché words[0]+1 non corrisponde a words[0+1].

Il primo indica il secondo carattere in words[0], mentre il secondo indica la seconda parola.

1

Sia lo stack che lo spazio heap vengono allocati dinamicamente, ovvero vengono allocati in fase di esecuzione. Il codice compilato è allocato dinamicamente, nell'heap o nello stack? Ovviamente nessuno dei due. Lo storage per costanti è simile all'archiviazione per il codice ... vengono memorizzati nell'eseguibile su disco e caricati in memoria di sola lettura. (Nota per i pedanti: questo è il modo in cui vengono eseguite le cose in un'implementazione tipica, non è richiesto dallo standard linguistico.)

words[0] è l'indirizzo del primo 'a' di "aaaa". Aggiungere 1 a quell'indirizzo dovrebbe sicuramente fornire l'indirizzo del secondo "a" di "aaaa". L'indirizzo di "bbbb" è finito a words[1].

Nel formato della tua stampa hai "(* words) [0]", ma è diverso. *words corrisponde a words[0]. (*words)[0] è lo stesso di **words, che è il primo 'a' (non il suo indirizzo) di "aaaa". Si stampa (*words)[0] con %c, non %s.

15

questo è come ..

enter image description here

poiché parole un array di carattere di puntatori così ogni indice array di parole terrà l'indirizzo della stringa letterale, cioè. indirizzo di base delle stringhe letterali se si stampano

printf("%s",words[0])// index 0 will print aaa.