2016-03-13 8 views
11

Capisco le basi di come funzionano i puntatori, ma il seguente esempio mi confonde.Qual è la differenza nei puntatori quando si definiscono char e int?

int *myNum = 10; // Produces an error 

char *myChar = "Something"; // Works fine 

Perché l'assegnazione di char funziona ma il numero intero no (Forse perché il char viene considerato come un array)?

Come pure ciò che mi confonde quando assegna direttamente una variabile puntatore, ottiene automaticamente un indirizzo?

char *myChar = "Something"; 

e

char myChar = "Something"; 
char *charAddr = &myChar; 

Quale sarebbe la differenza qui, o uguale?

+3

'char myChar =" Qualcosa ";' non funziona, perché '" Qualcosa "' non è un carattere. – immibis

+0

Quello che stai cercando è [Array to pointer conversion] (http://en.cppreference.com/w/c/language/conversion) – hgiesel

+0

@immibis ITYM '" Something "' non è implicitamente convertibile in 'char' . 'char myChar = 5.5;' è legale –

risposta

19
"Something" 

è essenzialmente abbreviazione di:

static const char some_hidden_array[] = {'S', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', '\0'}; 
some_hidden_array 

Cioè, quando si scrive "Something", il compilatore genera un allineamento dietro le quinte, e ti dà un puntatore all'inizio di quella matrice. Dal momento che questo è già un puntatore ad un char, non avrete alcun problema di assegnarlo a una variabile di tipo "puntatore a un char" (scritto come char*).

10 

è non abbreviazione di qualcosa di simile. È solo il numero 10 - non è un puntatore a un array che contiene il numero 10, o qualcosa del genere.

Nota che un char è un personaggio singolo, non è una stringa, che è il motivo per cui la sintassi della stringa è insolito rispetto alla maggior parte degli altri tipi - una stringa è diversi caratteri, non uno solo.Se si tenta di utilizzare una pianura vecchio char, vedrete la stessa cosa:

char *myChar = 'a'; // error 

o per qualsiasi altro tipo:

float *myFloat = 42.1f; // error 

In altre parole, non è strano che 10 dà un errore - semmai, è strano che "Something"non sia. (Almeno, è strano finché non si sa come funzionano gli stringhe letterali)

10

È la stessa cosa (non sta accadendo nessuna magia dal compilatore). Per impostazione predefinita, i valori letterali come 10 sono valori int, non int *.

È necessario lanciare:

int *myNum = (int*)10; // Need to cast 
char *myChar = "Something"; // No need to cast "..." is already a char* 

Nota che è pericoloso fare riferimento a un puntatore al valore assoluto come questo, perché si finirà con l'indirizzo 10 nella memoria della CPU.

Per quanto riguarda la seconda domanda, "..." viene considerato come una sequenza contigua di carattere in memoria simile a matrice e equivalente a char *.

Per una comprensione ponderata di C, dei puntatori e delle differenze tra array e puntatori, si dovrebbe leggere questo: Programmazione C avanzata: Deep C Secrets di Peter van der Linden.

+0

Grazie! Per quanto riguarda la seconda domanda, intendevo di più se quei 2 fossero uguali? Il primo esempio è un modo più breve per ottenere l'indirizzo? Grazie! –

+1

Ricordarsi di selezionare questa come risposta accettata se ha risposto alla domanda. –

+1

Fatto, grazie :) –

2

Quando si esegue char *myChar = "Something";, si crea una stringa letterale di sola lettura da qualche parte nella memoria, che termina con un carattere null. Ora questo è qualcosa di speciale con il compilatore, che interpreta un blocco di variabili "char" memorizzate continuamente e che terminano con un carattere null come stringa. Quindi in pratica hai creato una serie di caratteri e quando lo fai, *myChar*, restituisce la stringa.

In caso di numeri interi o altri tipi di dati, distingue tra int *ptr come puntatore a un numero intero e int ptr come numero intero. Probabilmente stai ricevendo un errore perché l'indirizzo che hai inserito potrebbe non essere valido/disponibile per te.

Inoltre, facendo

char myChar = "Something"; //this is an error, since char can hold one character 
char *charAddr = &myChar; 

noti che myChar e &myChar sono gli stessi, dal momento che myChar è un puntatore!

Edit: Fare riferimento qui circa letterali stringa: Is it possible to modify a string of char in C?

+0

Grazie per la spiegazione, quindi digita * var = qualcosa, crea sempre una variabile di sola lettura in memoria? E come da seconda domanda, ho più voluto dire se quei 2 sono uguali (modo più breve) :) Grazie! –

+0

@ J.Doe Sì. Date un'occhiata a questo: http://stackoverflow.com/questions/1011455/is-it-possible-to-modify-a-string-of-char-in-c –

+0

Grazie, questo aiuta molto. –

1

Mentre teoricamente la prima int *myNum = 10 senso — soprattutto se si sa c'è un utile int all'indirizzo dieci — in generale raramente è utile e potenzialmente molto pericoloso.

Tuttavia, ci sono alcune assegnazioni di puntatore, che sono ampiamente utilizzati e abbastanza sicuro:

int *myNum = 0; 

Su 99,9 +% delle moderne architetture di CPU, questo è lo stesso di

int *myNum = NULL; 

Vedere la definizione di NULL in <stddef.h>here.

Come regola generale, l'assegnazione di variabili puntatore è meglio farlo impostando all'indirizzo di qualcos'altro.

int k, *p = &k; 
+1

Grazie! Hmm così fondamentalmente, int * myNum = 10 // Puntatore a un indirizzo "10" e in realtà non è un indirizzo che contiene una variabile int con un valore di 10? –

+1

'int * myNum = 0;' è uguale a 'int * myNum = NULL;' su tutti i sistemi. Crea un puntatore nullo. Ti stai confondendo con il fatto che il puntatore nullo potrebbe non essere rappresentato da tutti i bit-zero (che non fa differenza con questo codice) –

+0

@ J.Doe Sì, e la tua confusione è praticamente esattamente il motivo per cui devi aggiungere il cast esplicito per rendere questo compilare - questo è quasi sempre un * errore *, piuttosto che il comportamento previsto. Su un moderno sistema desktop/server, davvero non si vogliono usare i puntatori per selezionare manualmente gli indirizzi. È stato utile in passato, tuttavia, ad esempio, per l'accesso diretto alla memoria grafica (o qualsiasi altro tipo di dispositivo, in realtà). Con l'astrazione dell'hardware, ci sono pochissimi usi legittimi (al di fuori del caso piuttosto ovvio '0' /' NULL', che per C standard * sempre * funziona :)). – Luaan

2

Perché assegnare il lavoro char ma integer non (forse causare char viene trattato come un array)?

Avete ragione, "Something" è una stringa letterale e può essere considerata come matrice di caratteri. Dopo char *myChar = "Something"; la seguente cosa accade: essa è allocata lunghezza + 1 byte di memoria dove "Something" saranno memorizzati, myChar viene indicate all'indirizzo iniziale di questa memoria. I valori letterali delle stringhe sono in qualche modo speciali.

Ecco un modo generale di inizializzazione array con valori costanti:

// valid initializations; 
char s2[] = { 'a', 'b', 'c' }; 
int a[] = { 1, 2, 3 }; 
char s1[] = "123"; 

Come pure quello che mi confonde quando si assegna direttamente una variabile puntatore, esso ottiene automaticamente un indirizzo?

Sì.

Date un'occhiata a 8.5.2 Character arrays of c++ docs

Problemi correlati