Qual è la differenza tra
char* name
che indica una stringa costante letterale e
const char* name
Qual è la differenza tra
char* name
che indica una stringa costante letterale e
const char* name
Risposte:
char*
è un puntatore mutabile a un carattere / stringa mutabile .
const char*
è un puntatore mutevole a un carattere / stringa immutabile . Non è possibile modificare il contenuto delle posizioni a cui punta questo puntatore. Inoltre, i compilatori sono tenuti a fornire messaggi di errore quando si tenta di farlo. Per lo stesso motivo, la conversione da const char *
a char*
è obsoleta.
char* const
è un puntatore immutabile (non può puntare a nessun'altra posizione) ma i contenuti della posizione in cui punta sono mutabili .
const char* const
è un puntatore immutabile a un carattere / stringa immutabile .
char const *
char *
fornisce un errore di segmentazione durante l'esecuzione?
const
se voglio che il compilatore dia l'errore se ho dimenticato e modificato i dati per errore, giusto?
char *name
È possibile modificare il carattere a cui name
punta e anche il carattere a cui punta.
const char* name
È possibile modificare il carattere in cui name
punti, ma non è possibile modificare il carattere in corrispondenza del quale punta.
correzione: è possibile modificare il puntatore, ma non il carattere a cui name
punta ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , vedere "Esempi" ). In questo caso, si const
applica lo specificatore char
, non l'asterisco.
Secondo la pagina MSDN e http://en.cppreference.com/w/cpp/language/declarations , il const
prima *
è parte della sequenza del decl-specificatore, mentre il const
dopo *
fa parte del dichiaratore.
Una sequenza di specificatori di dichiarazioni può essere seguita da più dichiaratori, motivo per cui const char * c1, c2
dichiara c1
come const char *
e c2
come const char
.
MODIFICARE:
Dai commenti, la tua domanda sembra porre la differenza tra le due dichiarazioni quando il puntatore punta a una stringa letterale.
In tal caso, non è necessario modificare il carattere in quali name
punti, in quanto potrebbe comportare un comportamento indefinito . I letterali di stringa possono essere allocati in aree di memoria di sola lettura (implementazione definita) e un programma utente non dovrebbe modificarlo in alcun modo. Qualsiasi tentativo di farlo comporta un comportamento indefinito.
Quindi l'unica differenza in quel caso (di utilizzo con valori letterali stringa) è che la seconda dichiarazione offre un leggero vantaggio. I compilatori di solito ti avvisano nel caso in cui tenti di modificare la stringa letterale nel secondo caso.
#include <string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[] = "Sample string";
strcpy(str1,source); //No warning or error, just Undefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
Produzione:
cc1: avvertenze trattate come errori
prog.c: nella funzione 'main':
prog.c: 9: errore: passando l'argomento 1 di 'strcpy' scarta i qualificatori dal tipo di target puntatore
Si noti che il compilatore avvisa per il secondo caso ma non per il primo.
name
punti in entrambi i casi potrebbero causare UB.
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)
constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error
constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok
// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";
lcharp[0] = 'X'; // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error
// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X'; // compile error
((char*)astr)[0] = 'X'; // ok
char *
valore genera un errore di segmentazione poiché stiamo cercando di modificare una stringa letterale (che è presente nella memoria di sola lettura)
In nessun caso è possibile modificare un valore letterale stringa, indipendentemente dal fatto che il puntatore a quel valore letterale stringa sia dichiarato come char *
o const char *
.
Tuttavia, la differenza è che se il puntatore è const char *
allora il compilatore deve fornire una diagnostica se si tenta di modificare il valore puntato, ma se il puntatore è char *
allora non lo è.
extern ... name
e avere *name = 'X';
. Sul "sistema operativo corretto", che potrebbe non funzionare, ma sui sistemi integrati, mi aspetto che faccia qualcosa di specifico per piattaforma / compilatore.
CASO 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Quanto sopra imposta str per indicare il valore letterale "Hello", che è codificato nell'immagine binaria del programma, che è contrassegnato come di sola lettura in memoria, significa che qualsiasi cambiamento in questo valore letterale di stringa è illegale e ciò comporterebbe errori di segmentazione.
CASO 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
CASO 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Il primo che puoi effettivamente cambiare se vuoi, il secondo che non puoi. Leggi sulla const
correttezza (ci sono alcune belle guide sulla differenza). C'è anche char const * name
dove non puoi reimpostarlo.
La domanda è qual è la differenza tra
char *name
che indica una stringa costante letterale e
const char *cname
Cioè dato
char *name = "foo";
e
const char *cname = "foo";
Non c'è molta differenza tra i 2 ed entrambi possono essere visti come corretti. A causa della lunga eredità del codice C, i letterali delle stringhe hanno avuto un tipo di char[]
, no const char[]
, e ci sono molti vecchi codici che accettano anche al char *
posto di const char *
, anche quando non modificano gli argomenti.
La principale differenza dei 2 in generale è che *cname
o cname[n]
valuteranno valori di tipo const char
, mentre *name
o name[n]
valuteranno valori di tipo char
, che sono valori modificabili . È richiesto un compilatore conforme per produrre un messaggio di diagnostica se la destinazione dell'assegnazione non è un valore modificabile ; non è necessario generare alcun avviso in caso di assegnazione a valori di tipo char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
Il compilatore non è tenuto a interrompere la compilazione in entrambi i casi; è sufficiente che produca un avviso per l'assegnazione a cname[0]
. Il programma risultante non è un programma corretto . Il comportamento del costrutto non è definito . Potrebbe bloccarsi, o peggio ancora, potrebbe non arrestarsi e potrebbe modificare letteralmente la stringa in memoria.
In realtà, char* name
non è un puntatore a una costante, ma un puntatore a una variabile. Potresti parlare di quest'altra domanda.