Cosa sta facendo malloc in questo codice?

Potresti spiegare il seguente codice?

str = (char *) malloc (sizeof(char) * (num+1)); 
  1. Cosa sta facendo malloc qui?
  2. Perché è usato num + 1 ?

malloc è una funzione che assegna un blocco di memoria all’heap e restituisce un puntatore ad esso. È simile al new operatore in molte lingue. In questo caso, sta creando un blocco di memoria che può sopravvivere per un periodo di tempo arbitrario e avere una dimensione arbitraria. Questo di per sé è materiale abbastanza approfondito, che è alquanto difficile da spiegare e garantisce una domanda separata.

Il num + 1 compensa il terminatore nullo alla fine delle stringhe. Le stringhe spesso hanno bisogno di sapere quanto tempo sono, e la tradizione C è di allocare spazio per un carattere addizionale alla fine della stringa, che sarà sempre il carattere speciale \0 . Ciò consente alle funzioni che si occupano della stringa di determinare automaticamente la dimensione della stringa. Ad esempio, se volessi fare qualcosa per ogni carattere di una stringa senza sapere per quanto tempo la stringa è, potresti fare qualcosa del genere:

 const char *ptr = str; while (*ptr != '\0') { process(*ptr); ptr++; } 

malloc è per l’allocazione di memoria. num + 1 è di consentire il null-terminator – \0 .

Preambolo: non posso crederci! Sono rimasto sconcertato da questo tipo di espressione quando mi hanno insegnato i principi fondamentali del C (nessun gioco di parole). Questo è il motivo per cui vado nei dettagli estremi nella sezione “analizzare il codice”.

Analisi del codice

Il primo problema è l’analisi del codice

Benvenuto nella Twilight Zone

 str = (char *) malloc (sizeof(char) * (num+1)); 

Quando si lavora con C / C ++, l’analisi di questo tipo di espressione è obbligatoria, quindi la suddivideremo nei suoi componenti. La prima cosa che vediamo qui è qualcosa di simile:

 variable = (expression) function (expression) ; 

La prima volta che l’ho visto, ero solo “Ehi, non posso credere che ci sia un linguaggio di programmazione in cui puoi chiamare una funzione mettendo i suoi parametri sia a sinistra sia a destra della chiamata di funzione!”.

Analizzando questa riga di codice?

In verità, questa riga dovrebbe essere letta come:

 variable = function_a (function_b (expression)) ; 

dove :

 expression is sizeof(char) * (num+1) function_b is malloc function_a is a cast operator 

L’operatore di cast di C è alquanto meno naturale

Come già spiegato altrove, l’operatore di cast in stile C è più simile

 (function_a) expression 

di più naturale

 function_a(expression) 

Il che spiega la stranezza dell’intera linea di codice.

C ++ ha qualcosa di più comprensibile?

Nota che in C ++ puoi usare entrambe le notazioni, ma dovresti invece usare il static_cast, const_cast, reinterpret_cast o dynamic_cast invece delle notazioni di cui sopra. Usando un cast di C ++, la riga di codice sopra sarebbe:

 str = static_cast ( malloc (sizeof(char) * (num+1)) ) ; 

Il mio sizeof è più grande del tuo

sizeof è un operatore. Puoi pensare come una funzione che lavora sui tipi. Passi un tipo come parametro e ti darà le sue dimensioni in byte.

Quindi, se scrivi:

 size_t i = sizeof(char) ; size_t j = sizeof(int) ; 

Probabilmente avrai (su Linux a 32 bit) un valore 1 per i, e 4 per j. Il suo uso in malloc è come dire “Voglio abbastanza spazio per mettere 25 auto di 4 metri di lunghezza” invece di “Voglio almeno 100 metri”.

C’è qualcosa riguardo a Malloc

Il parametro di Malloc è un size_t, cioè un numero intero senza segno. Gli dai la dimensione in byte e, se ha successo, ti restituisce l’indirizzo della memoria allocata abbastanza grande da poter essere usato come array. Per esempio:

 int * p = (int *) malloc (25 * sizeof(int)) ; 

Quindi p punta a una memoria in cui puoi mettere 25 numeri interi uno accanto all’altro, come se all’interno di un array i cui indici passassero da zero alla dimensione minux. Per esempio:

 p[0] = 42 ; // Ok, because it's the 1st item of the array p[24] = 42 ; // Ok, because it's the 25th item of the array p[25] = 42 ; // CORRUPTION ERROR, because you are trying to // use the 26th item of a 25 items array ! 

Nota: si dispone anche di aritmetica dei puntatori, ma ciò va oltre lo scopo della domanda.

num + 1?

Le stringhe in stile C sono leggermente diverse dalle stringhe di altre lingue. Ogni carattere di una stringa può essere di qualsiasi valore, MA NON ZERO. Perché zero (anche indicato \ 0) segna la fine della stringa ac.

Detto in un altro modo: non si conosce mai la dimensione di una stringa di c, ma cercando il carattere \ 0, è ansible sapere dove finisce (che è uno dei motivi di overflow del buffer e di danneggiamento dello stack, comunque).

Ad esempio, la stringa “Hello” sembra avere 5 caratteri:

 "Hello" seems to be an array containing 'H', 'e', 'l', 'l' and 'o'. 

Ma in verità, ha 6 caratteri, l’ultimo è il carattere ZERO, che viene annotato usando il carattere di escape \ 0. Così:

 "Hello" is an array containing 'H', 'e', 'l', 'l', 'o' and 0. 

Questo spiega che quando si desidera allocare spazio sufficiente per una stringa di caratteri “num”, si assegnano invece caratteri “num + 1”.

malloc alloca la memoria.

num + 1 come num è il numero di caratteri nella stringa e +1 per il terminatore nullo

In questo caso, Malloc assegna num + 1 volte sizeof (char) byte. Questa è una pratica standard quando si desidera allocare una serie di elementi. Il carattere in sizeof (char) viene in genere sostituito con il tipo di array assegnato.

In senso stretto, in questo esempio, la dimensione di (char) non è necessaria. È garantito che sia della taglia 1 secondo lo standard C e quindi si moltiplica per 1.

malloc alloca un array di caratteri (in questo caso) sull’heap.

l’array sarà num + 1 lungo, ma la stringa più lunga che può contenere è ‘num’ long, perché la stringa in C ha bisogno di un null byte finale.

Malloc alloca la memoria, in questo caso per la stringa str di lunghezza num. (char *) è il tipo per str sizeof (char) è il numero di byte richiesto per ogni carattere. Il +1 è per il carattere null finale nella stringa, normalmente zero.

Malloc è una chiamata per allocare memoria.

Il codice di cui sopra sta per allocare spazio per num + 1 caratteri. Probabilmente c’è una stringa con caratteri numerici dentro e l’autore del codice ha aggiunto spazio per il terminatore null.

Dopo la chiamata str indicherà l’inizio di quel blocco di memoria che è stato assegnato.

Questo codice tenta di allocare un blocco di memoria che può contenere num + 1 valori di tipo char. Quindi se una chat è uguale a un byte e num 10, tenterà di allocare 11 byte di memoria e restituirà un puntatore a quella memoria.

È probabile che +1 sia usato perché il programmatore voleva memorizzare una stringa (matrice di caratteri) di caratteri num e ha bisogno di un carattere extra per memorizzare il carattere terminante ‘\ 0’ (null). In C / C ++. le stringhe chracater sono, per convenzione, terminate da un carattere null.

malloc assegna la memoria dall’heap e restituisce un puntatore ad essa. È utile quando non sai quanta memoria hai bisogno in fase di compilazione.

Per quanto riguarda il motivo (num + 1), dipende davvero da cosa sta facendo il codice … forse num è il numero di caratteri nella stringa, e il +1 è per il byte terminatore NUL alla fine. In questo caso, non so a cosa serva la dimensione di (char).

 sizeof(char) 

è salvo. Non si dovrebbe assumere un singolo byte per carattere.

La mia domanda è cosa stai programmando se non sai cosa fa malloc?

 man malloc 

su un sistema Linux. Su Windows. chissà? Probabilmente 17 clic del mouse.