Puntatori e valori in C

-1

Lavoro molto in varie lingue, molte delle quali sono linguaggi di scripting come JavaScript, Shell Scripting, PHP e così via. Ma lavoro molto anche con Java, che è più vicino a un linguaggio più "reale".

C / C ++ è sempre stato un interesse, ma non mi è servito molto. Ho avuto alcune piccole cose in alcuni progetti Java che dovevano essere delegati a una soluzione più veloce, soprattutto quando si trattava di un sacco di operazioni sui file. Per questo ho usato C ++ perché ha alcune astrazioni come la stringa e tale che mi permette di evitare la maggior parte degli stili di puntatore di C "*".

Ma non sono riuscito a ottenere tutto in C ++, ho solo letto quello di cui avevo bisogno per farlo funzionare. E fare qualcosa senza sapere pienamente quello che stai facendo, può causare problemi. Ad esempio, è facile creare perdite di memoria senza problemi con il compilatore. Solo perché qualcosa compila e corre, non significa che non abbia problemi.

Quindi ora ho deciso di passare un po 'di tempo con questo correttamente. E non C ++, perché tu stai ancora impegnando C per molto tempo, quindi meglio capirlo prima, prima di iniziare con l'altro.

Per la maggior parte C è abbastanza facile. Quello che trovo problematico sono i suggerimenti. So quali sono i suggerimenti. Ma nella maggior parte delle lingue lavori con riferimenti e non con puntatori direttamente, quindi mi sta dando un po 'di grattacapi per capire esattamente a cosa sto lavorando alcune volte.

Esempio

char *cvar; 

cvar = "";
*cvar = "";

Nell'esempio sopra, credo che il primo sia corretto? Il secondo tenta di cambiare il puntatore e non il contenuto?

char *cvar = "";

Ma se è così, perché è corretto? I valori letterali restituiscono valori o indicatori? Perché le cuciture come se varia o mi sbaglio quando lavoro con valori o puntatori.

function name(char *arg) {

}

name(&cvar);

C passa per valore, quindi cosa ottengo nella funzione? Puntatore copiato che punta allo stesso luogo / valore?

    
posta Daniel B 13.04.2018 - 23:08
fonte

1 risposta

3

Per le dichiarazioni C, dobbiamo distinguere tra matrici e puntatori.

Le matrici riservano l'archiviazione per i loro elementi e i riferimenti di un array vengono trattati come valori di puntatore (al loro primo elemento) ogni volta che vengono utilizzati in un'espressione.

char *cvar; 

Il precedente dichiara l'identificatore come puntatore e riserva l'archiviazione per quel puntatore; il puntatore è altrimenti non inizializzato. In un contesto globale questa memoria verrà azzerata (inizializzazione modulo in un'altra unità di compilazione). In un contesto locale, lo spazio di archiviazione non è inizializzato (vale a dire ha spazzatura). Questa dichiarazione non coinvolge un array.

cvar = "hello world\n"; 

Il precedente fa due cose:

  • per prima cosa, aggiunge un valore null alla stringa letterale, quindi assegna una matrice per la stringa letterale: "hello world \ n \ 0". L'allocazione per tali letterali è sempre statica, cioè diventa una costante byte / char array inizializzata nello spazio globale (indipendentemente dal contesto di utilizzo della stringa letterale).

  • secondo, dopo l'esecuzione se locale, o primordialmente, se globale, l'assegnazione stessa pone l'indirizzo del primo elemento dell'array di byte letterale della stringa statica nella variabile pointer.

*cvar = "hi";

Questo sopra privo di senso, in quanto è una mancata corrispondenza di tipo. *cvar rappresenta un singolo carattere: quello puntato da cvar . Un array-of-char, il letterale stringa "ciao \ 0", diventa un puntatore al carattere nel contesto dell'espressione - e non possiamo assegnare un puntatore al carattere a un singolo carattere (non andrà bene più è una mancata corrispondenza di tipo). (Inoltre, si noti che il valore del puntatore in cvar non è inizializzato (o inizializzato in qualche contesto non mostrato).)

I believe the first one is correct?

Si

The second one tries to change the pointer and not the content?

No, prova a usare il puntatore per cambiare ciò che viene indicato.

why is this then correct?

Perché è semplicemente la combinazione delle tue prime due dichiarazioni, scritte come una.

Does the literals return values or pointers?

Entrambi, una specie di. I letterali sono array di byte inizializzati, che convertono in puntatori al primo elemento (in uso, proprio come tutti gli array). Informalmente, i puntatori sono le variabili che contengono gli indirizzi e gli indirizzi sono valori che possono essere utilizzati nelle espressioni (purché i tipi corrispondano correttamente) proprio come gli interi.

C parses[sic: "passes"] by value, so what do I get in the function? Copied pointer that points to the same place/value?

function name(char *arg);
...
name(&cvar);

Può essere analizzato come:

char *arg = &cvar;
  • arg è un pointer-to-char come per la sua dichiarazione.
  • come cvar è già di per sé un puntatore-a-carattere (da più in alto), quindi &cvar è un puntatore-a-puntatore-a-carattere.

Quindi questo incarico è anche un tipo non corrispondente.

Potresti anche cercare

char carr [] = "hello world\n";

Qui il letterale stringa viene preso come inizializzatore dell'array anziché come letterale stringa vero.

Se questa dichiarazione è vista nel contesto globale, la memoria statica non è riservata al letterale, solo per la matrice stessa (che è inizializzata come previsto).

Se questa dichiarazione è vista in un contesto locale, il letterale può essere memorizzato da qualche parte, ma non vedremo mai dove sia perché verrebbe usato solo internamente per inizializzare carr (che avverrà quando il flusso di controllo raggiunge l'assegnazione di inizializzatore) e l'array carr è tutto ciò che possiamo osservare dall'interno del linguaggio; Non possiamo osservare l'indirizzo della stringa letterale come possiamo con char *cvar = "hi"; , o qualcosa come printf("%s\n", "hi") ).

    
risposta data 14.04.2018 - 00:13
fonte

Leggi altre domande sui tag