Differenza tra l'utilizzo di puntatori e matrici di caratteri
Domanda
Domanda di base.
char new_str[]="";
char * newstr;
Se devo concatenare alcuni dati in esso o utilizzare funzioni stringa come strcat / substr / strcpy, qual è la differenza tra i due?
Capisco che devo allocare memoria all'approccio char * (Riga # 2). Non sono sicuro di come.
E const char * e letterali stringa sono gli stessi?
Ho bisogno di saperne di più su questo. Qualcuno può indicare un contenuto / materiale esauriente?
Soluzione
Leggi questo articolo di seguito:
Vedi anche in caso di array di caratteri come nel tuo caso, char new_str [] quindi new_str punterà sempre alla base dell'array. Il puntatore in sé non può essere incrementato. Sì, è possibile utilizzare gli script per accedere al carattere successivo nell'array, ad esempio: new_str [3]
;
Ma in caso di puntatore a carattere, il puntatore può essere incrementato new_str ++
per recuperare il carattere successivo nella matrice.
Vorrei anche suggerire questo articolo per maggiore chiarezza .
Altri suggerimenti
La fonte eccellente per chiarire la confusione è Peter Van der Linden, Esperto in Programmazione C, segreti di Deep C - che gli array e i puntatori non sono gli stessi nel modo in cui vengono affrontati nella memoria.
Con un array
char new_str[];il compilatore ha fornito a new_str un indirizzo di memoria noto sia in fase di compilazione che in fase di esecuzione, ad es. 0x1234, quindi l'indicizzazione di new_str è semplice utilizzando
[]
. Ad esempio new_str [4]
, in fase di esecuzione, il codice seleziona l'indirizzo in cui new_str
risiede, ad es. 0x1234 (che è l'indirizzo nella memoria fisica). aggiungendo lo specificatore di indice [4]
, 0x1234 + 0x4, il valore può quindi essere recuperato.
Considerando che, con un puntatore, il compilatore fornisce al simbolo
char *newstrun indirizzo, ad es. 0x9876, ma in fase di esecuzione, quell'indirizzo utilizzato è uno schema di indirizzamento indiretto. Supponendo che newstr sia stato mallocato
newstr = malloc(10);, ciò che sta accadendo è che, ogni volta che viene fatto un riferimento nel codice per utilizzare newstr, poiché l'indirizzo del newstr è noto dal compilatore, ovvero 0x9876, ma ciò che punta a newstr è variabile . In fase di esecuzione, il codice recupera i dati dalla memoria fisica 0x9876 (ovvero newstr), ma a quell'indirizzo è un altro indirizzo di memoria (dal momento che l'abbiamo mallocato), ad esempio 0x8765 è qui, il codice recupera i dati da quell'indirizzo di memoria che malloc assegnato a newstr, ovvero 0x8765.
Il char new_str []
e char * newstr
sono usati in modo intercambiabile, poiché un indice di elemento zeroth dell'array decade in un puntatore e questo spiega perché potresti newstr [5]
o * (newstr + 5)
Nota come viene usata l'espressione del puntatore anche se abbiamo dichiarato char * newstr , quindi
*(new_str + 1)
= *newstr;
OR *(new_str + 1)
= newstr[1];
In sintesi, la vera differenza tra i due è come si accede alla memoria.
Prendi il libro, leggilo, vivi e respira. È un libro geniale! :)
Questa è una matrice di caratteri:
char buf [1000];
Quindi, per esempio, questo non ha senso:
buf = &some_other_buf;
Questo perché buf
, sebbene abbia caratteristiche di tipo pointer, sta già indicando l'unico posto che ha senso per questo.
char *ptr;
D'altra parte, ptr
è solo un puntatore e può puntare da qualche parte. Molto spesso, è qualcosa del genere:
ptr = buf; // #1: point to the beginning of buf, same as &buf[0]
o forse questo:
ptr = malloc (1000); // #2: allocate heap and point to it
o
ptr = "abcdefghijklmn"; // #3: string constant
Per tutti questi, * ptr può essere scritto in & # 8212; tranne il terzo caso in cui alcuni ambienti di compilazione definiscono le costanti di stringa come non scrivibili.
*ptr++ = 'h'; // writes into #1: buf[0], #2: first byte of heap, or
// #3 overwrites "a"
strcpy (ptr, "ello"); // finishes writing hello and adds a NUL
La differenza è che uno è un puntatore, l'altro è un array. È possibile, ad esempio, array sizeof (). Potresti essere interessato a sbirciare qui
Se stai usando C ++ come indicato dai tuoi tag, dovresti davvero usare le stringhe C ++, non gli array C char
.
Il tipo string
semplifica notevolmente la manipolazione delle stringhe.
Se per qualche motivo sei bloccato con le matrici char
, la riga:
char new_str[] = "";
alloca 1 byte di spazio e vi inserisce un carattere di terminazione null. È leggermente diverso da:
char *new_str = "";
poiché ciò può darti un riferimento alla memoria non scrivibile. La dichiarazione:
char *new_str;
da solo ti dà un puntatore ma nulla a cui punta. Può anche avere un valore casuale se è locale in una funzione.
Ciò che le persone tendono a fare (in C piuttosto che in C ++) è fare qualcosa del tipo:
char *new_str = malloc (100); // (remember that this has to be freed) or
char new_str[100];
per avere abbastanza spazio.
Se usi le funzioni str ...
, sei fondamentalmente responsabile di assicurarti di avere abbastanza spazio nell'array char
, per non avere tutti i tipi di pratica strana e meravigliosa nel debug del codice. Se usi stringhe C ++ reali, gran parte del lavoro grugnito è fatto per te.
Il tipo del primo è char [1], il secondo è char *. Diversi tipi.
Alloca memoria per quest'ultima con malloc
in C o new
in C ++.
char foo[] = "Bar"; // Allocates 4 bytes and fills them with
// 'B', 'a', 'r', '\0'.
La dimensione qui è implicita dalla stringa di inizializzazione.
I contenuti di foo
sono mutabili. Puoi cambiare foo [i]
ad esempio dove i
= 0..3.
OTOH se lo fai:
char *foo = "Bar";
Il compilatore ora alloca una stringa statica " Bar " nella memoria di sola lettura e non può essere modificato.
foo[i] = 'X'; // is now undefined.
char new_str[]="abcd";
Questo specifica una matrice di caratteri (una stringa) di dimensione 5 byte (un byte per ogni carattere più uno per il terminatore null). Quindi memorizza la stringa 'abcd' in memoria e possiamo accedere a questa stringa usando la variabile new_str.
char *new_str="abcd";
Questo specifica che una stringa 'abcd' è memorizzata da qualche parte nella memoria e il puntatore new_str punta al primo carattere di quella stringa.
Per differenziarli nel lato di allocazione della memoria:
// With char array, "hello" is allocated on stack
char s[] = "hello";
// With char pointer, "hello" is stored in the read-only data segment in C++'s memory layout.
char *s = "hello";
// To allocate a string on heap, malloc 6 bytes, due to a NUL byte in the end
char *s = malloc(6);
s = "hello";
Se sei in c ++, perché non usare std :: string per hai bisogno di tutte le tue stringhe? Soprattutto tutto ciò che riguarda la concatenazione. Questo ti salverà da molti problemi.