Come per tutto ciò che sembra più spaventoso all'inizio di quanto non fosse in seguito, il modo migliore per superare la paura iniziale è immergersi nel disagio dell'ignoto ! A volte è come quello che impariamo di più, dopo tutto.
Sfortunatamente, ci sono delle limitazioni. Mentre stai ancora imparando a usare una funzione, non dovresti assumere il ruolo di insegnante, per esempio. Leggo spesso le risposte di coloro che apparentemente non sanno come usare realloc
(cioè la risposta attualmente accettata! ) Dicendo agli altri come usarlo in modo errato, a volte con il pretesto di aver omesso la gestione degli errori , anche se si tratta di una trappola comune che deve essere menzionato. Ecco una risposta che spiega come utilizzare realloc
correttamente . Si noti che la risposta memorizza il valore restituito in una variabile diversa per eseguire il controllo degli errori.
Ogni volta che si chiama una funzione e ogni volta che si utilizza un array, si utilizza un puntatore. Le conversioni si stanno verificando implicitamente, cosa che dovrebbe essere ancora più spaventosa, poiché sono le cose che non vediamo che spesso causano la maggior parte dei problemi. Ad esempio, perdite di memoria ...
Gli operatori di matrice sono operatori di puntatore. array[x]
è davvero una scorciatoia per *(array + x)
, che può essere suddivisa in: *
e (array + x)
. È molto probabile che *
sia ciò che ti confonde. Possiamo eliminare ulteriormente l'aggiunta dal problema ipotizzando x
essere 0
, quindi, array[0]
diventa *array
perché l'aggiunta 0
non cambierà il valore ...
... e quindi possiamo vedere che *array
è equivalente a array[0]
. Puoi usarne uno dove vuoi usare l'altro e viceversa. Gli operatori di matrice sono operatori di puntatore.
malloc
, realloc
E gli amici non inventano il concetto di un puntatore che hai utilizzato per tutto il tempo; usano semplicemente questo per implementare qualche altra caratteristica, che è una diversa forma di durata della memoria, più adatta quando desideri cambiamenti drastici e dinamici delle dimensioni .
È un peccato che la risposta attualmente accettata vada anche contro la consistenza di alcuni altri consigli molto fondati su StackOverflow e, allo stesso tempo, manca un'opportunità per introdurre una funzione poco nota che brilla proprio per questo caso: array flessibile membri! In realtà è una risposta piuttosto sbagliata ... :(
Quando si definisce il proprio struct
, dichiarare l'array alla fine della struttura, senza alcun limite superiore. Per esempio:
struct int_list {
size_t size;
int value[];
};
Ciò ti consentirà di unire il tuo array int
nella stessa allocazione del tuo count
e averli associati in questo modo può essere molto utile !
sizeof (struct int_list)
agirà come se value
avesse una dimensione di 0, quindi ti dirà la dimensione della struttura con un elenco vuoto . Devi ancora aggiungere le dimensioni passate realloc
per specificare le dimensioni del tuo elenco.
Un altro suggerimento utile è ricordare che realloc(NULL, x)
equivale a malloc(x)
, e possiamo usarlo per semplificare il nostro codice. Per esempio:
int push_back(struct int_list **fubar, int value) {
size_t x = *fubar ? fubar[0]->size : 0
, y = x + 1;
if ((x & y) == 0) {
void *temp = realloc(*fubar, sizeof **fubar
+ (x + y) * sizeof fubar[0]->value[0]);
if (!temp) { return 1; }
*fubar = temp; // or, if you like, `fubar[0] = temp;`
}
fubar[0]->value[x] = value;
fubar[0]->size = y;
return 0;
}
struct int_list *array = NULL;
Il motivo che ho scelto di usare struct int_list **
come primo argomento potrebbe non sembrare immediatamente ovvio, ma se pensi al secondo argomento, eventuali modifiche apportate value
dall'interno push_back
non sarebbero visibili alla funzione da cui stiamo chiamando, giusto? Lo stesso vale per il primo argomento, e dobbiamo essere in grado di modificare il nostro array
, non solo qui ma probabilmente anche in qualsiasi altra funzione / i lo passiamo a ...
array
inizia indicando il nulla; è un elenco vuoto. Inizializzarlo equivale ad aggiungerlo. Per esempio:
struct int_list *array = NULL;
if (!push_back(&array, 42)) {
// success!
}
PS Ricordati difree(array);
quando hai finito!