← Tutti i video

Array Dinamici in C

Guarda su YouTube → 35:18 14 settembre 2025

Descrizione

Ciao, oggi vediamo come implementare un array dinamico in C. Alla fine del video mostro una macro in C che implementa la logica di resize principale dell'array dinamico. Come al solito, spero il video sia utile e formativo. Se vuoi supportare il mio lavoro :) - https://www.patreon.com/hexdump Se vuoi imparare la Web Application Security: - https://www.udemy.com/course/practical-wapt/?referralCode=15450B3828BA5A3B23CB Se vuoi imparare la Linux Privilege Escalation: - https://www.udemy.com/course/linux-privesc/?couponCode=33738F67D2C09EB25600 Se sei interessato ai miei servizi di formazione: - https://esadecimale.it ------------------------- TIMESTAMP 00:00 Che cos'è un array dinamico? 07:00 La struttura 13:00 Una prima implementazione 17:00 Gestione errori 22:00 Uniformiamo 25:00 Macro

Commenti 28

I commenti vengono da YouTube e sono aggiornati periodicamente.

  1. @baxleone 14 gennaio 2026
    Sembra spiegato bene e con cura. Mi devo ripassare un po' di cose.
  2. @GabrieleZancanella 14 settembre 2025
    Ottimo video. Spiegazione progressiva ben fatta motivando il perché delle scelte effettuate. Bravo.
  3. @hamilnvt6191 15 settembre 2025 2
    Ringraziamo Tsoding, amen🙏🏻 Ottimo video!
    1 risposta
    1. @esadecimale Autore 15 settembre 2025 1
      Il grande Tsoding ❤️
  4. @zerouno-dev 26 settembre 2025
    Ciao Leonardo! Questo video è bellissimo per almeno un paio di motivi. Il primo è che, utilizzando lo C, non dà nulla per scontato e fa vedere quello che c'è sotto alcune funzionalità dei linguaggi di alto livello. Il secondo (e questa è un'opinione molto personale) è che mostra anche i limiti dello C. O, per meglio dire, della sua standard library. Mi spiego meglio. Se dovessimo utilizzare lo C per applicazioni non banalissime saremmo costretti a scriverci un sacco di roba: array dinamici, liste linkate, code, pile, stringhe, stringhe unicode, ecc.). Personalmente trovo che l'approccio del C++ siamo molto più pragmatico e moderno. Ovviamente, quale che sia la mia opinione personale... Lunga vita allo C! 🙂
    2 risposte
    1. @esadecimale Autore 26 settembre 2025 1
      Si hai centrato il punto, infatti molti dev di successo che programmano in C se poi vai a vedere lavorano con essenzialmente delle loro librerie che si sono implementati nel corso del tempo. Questo per roba tipo manipolazione di stringhe, allocazione della memoria, e poi magari in contesti specifici anche wrapper di altre librerie. E queste librerie sono frutto di anni di dev, sicuramente non te le tiri fuori in una singola botta per un singolo progetto. Sarà forse una filosofia del linguaggio, il fatto che la standard lib di C è oggettivamente scarsa? Nel senso: ti forza a scriverti la tua roba. Sembra un downside, e per certi aspetti lo è effettivamente, ma allo stesso tempo ti incentiva ad essere più indipendente.
    2. @zerouno-dev 26 settembre 2025
      @esadecimale io penso di si: credo sia proprio la filosofia del linguaggio: minimale ma molto "libero". Credo sia un linguaggio che ti dà l'illusione di conoscerlo me che, in realtà, lascia aperte un'infinità di considerazioni e conseguenze non banali, a volte addirittura cruciali. Io lo adoro (l'ho imparato ai tempi della scuola, più di 30 anni fa). Ultimamente sto studiano il C++ e lo trovo un ottimo compromesso. Alla fine non credo di poter creare un array dinamico in un modo migliore di quello proposto dalla standard library... ;-)
  5. @zordak112 14 settembre 2025
    28:15 Veramente si puo' fare una cosa del genere? non sapevo sizeof potesse valutare i suoi argomenti!
    1 risposta
    1. @esadecimale Autore 15 settembre 2025
      Provare per credere! Felice di far scoprire cose nuove :)
  6. @omegaslime9605 14 settembre 2025 1
    Piccola domanda: ma nella macro, al posto del trucco del do-while, andrebbe lo stesso bene inserire delle parentesi graffe, per denotare il blocco? (Potrei provarlo sul mio PC appena possibile ma trovavo questa domanda interessante da lasciarla sotto al video)
    2 risposte
    1. @omegaslime9605 14 settembre 2025
      PS: comunque bel video, bella spiegazione, bel modo di insegnare, grazie❤
    2. @esadecimale Autore 14 settembre 2025 1
      @omegaslime9605 Ottima domanda, hai fatto bene a lasciarla qui! Allora, non funziona perché {} non rappresenta uno statement ma uno scope, quindi si comporta in modo diverso. Per esempio se fai if (condt) DA_APPEND(); else DA_APPEND();, con il {} ti da errore, perché è come se facessi if (cond) {}; else Ma questa cosa in C non va bene Anche se togli il semicolon comunque con le curly braces e basta è generalmente meno stabile. Molto meglio il do while
  7. @angelofiorillo-sp1fp 14 settembre 2025
    Personalmente si potrebbe migliorare il codice partendo dalla struct posizionando il puntatore a data alla fine si può sfruttare la località spaziale tra metadati e dati effettivi ( è una pratica consolidata, l’ha mostrata anche Antirex in uno dei video sul corso c). Inoltre userei i puntatori alla struttura in modo da potere de allocare non solo i dati ma tutta la struttura. Ultimo refactor eliminerei i magic number, il 256 ma soprattutto il 2 che poi hai un po’ minimizzato ma deriva dall’analisi ammortizzata.
    7 risposte
    1. @esadecimale Autore 14 settembre 2025
      La struttura in questo caso pesa poco, quindi può essere tranquillamente allocata nello stackframe come variabile locale, e se hai bisogno di un lifetime più lungo la metti come variabile globale. Personalmente meno cose ho allocate dinamiche più dormo tranquillo. Per i magic numbers, onestamente non introdurrei un parametro in più neanche a livello di DEFINE per quel magic number, ma semplicemente perché sarebbe molto poco utilizzato nella maggior parte dei contesti, dato che 256 basta e avanza. Come dire: è un dettaglio implementativo della struttura che raramente il programmatore dovrà cambiare, e dunque trovo più sensato non introdurre un simbolo in più per parametrizzare questa cosa. Ovviamente queste sono scelte di design. Da questo punto di vista tendo ad avere un approccio molto pragmatico.
    2. @angelofiorillo-sp1fp 14 settembre 2025
      @esadecimalenon sono assolutamente d’accordo avresti sempre una sola malloc con il vantaggio di avere metadati e dati in locazioni cotigue senza rischiare cache miss, questa è una scelta di design sensata secondo me. In più non ho mai visto librerie professionali che lavorano direttamente sulle struct piuttosto che con i puntatori a struttura.
    3. @esadecimale Autore 14 settembre 2025
      ​@angelofiorillo-sp1fp Rispetto il tuo punto di vista, e sulle cache-miss mi trovi d'accordo, nel senso che se si evitano è meglio. Non ho studiato in dettaglio le logiche di allocazione del malloc, quindi li da chiedersi se effettuo due malloc() di fila è sempre detto che le allocazioni sono contigue? considerando che sono size diversi che allochi. Quindi magari utilizza delle strutture interne diverse per i vari blocchi. Probabilmente dipende anche dallo stato globale della memoria. Da approfondire comunque, ottimo spunto, ti ringrazio. Per il resto, l'ultimo punto che poni non è proprio una argomentazione del perché è una scelta migliore utilizzare il puntatore.
    4. @angelofiorillo-sp1fp 14 settembre 2025
      @esadecimalenon hai compreso quello che volevo dire nella stessa malloc della struct allochi lo spazio extra anche per data
    5. @angelofiorillo-sp1fp 14 settembre 2025
      typedef struct { size_t capacity; size_t size; int data[]; // flexible array member (C99+) } dynamic_array; dynamic_array *create_dynamic_array(size_t capacity) { dynamic_array *arr = malloc(sizeof(dynamic_array) + capacity * sizeof(int)); if (!arr) { return NULL; } arr->capacity = capacity; arr->size = 0; return arr; }
    6. @esadecimale Autore 14 settembre 2025
      @angelofiorillo-sp1fpe ma poi quando cresce e fai il realloc()? non cambia l’indirizzo? e se ogni volta riallochi pure la struct, allora devi aggiornare tutte le volte in cui utilizzi quel puntatore
    7. @esadecimale Autore 14 settembre 2025
      Penso che nella logica del realloc lui sicuramente ottimizza cercando di estendere in modo lineare la memoria, ma comunque non è garantito, quindi cambia molto dallo stato del programma
  8. @giuseppemodugno6161 14 settembre 2025 1
    Quel trucco della macro è simpatico, ma rimane un trucco. Non mi piacerebbe usarlo in un codice di produzione. Al massimo userei una macro per definire in modo semplice una funzione da_append_i(), da_append_f(), da_append_s(), ecc... (da starebbe per dynamic array)
    2 risposte
    1. @esadecimale Autore 14 settembre 2025 3
      Sicuramente le macro sono piu rognose a livello di debug, una funzione ti darebbe più visibilità. Detto questo la logica della funzione è molto semplice, quindi ci potrebbe anche stare. Alla fine è un wrapper di realloc, e se metti qualche asset nella macro ottieni nuovamente capacità di debugging ok
    2. @giuseppemodugno6161 14 settembre 2025
      ​@esadecimalein genere io preferisco usare funzioni static inline (eventualmente definite in un .h) piuttosto che macro function-like. Poi questo tuo uso delle macro mi fa venire in mente una nuova funzionalità di una recente versione del C (forse C23). Se non sbaglio è chiamata macro generic
  9. @AccountTemppp 27 novembre 2025
    Non è effettivamente poco sensato usato realloc? Dato che la memoria precedentemente usata resta frammentata
    4 risposte
    1. @esadecimale Autore 27 novembre 2025
      No, realloc prova ad estendere il blocco in modo contiguo, ma se non riesce a garantire la continuità degli indirizzi ne alloca un nuovo blocco grosso, fa il free di quello vecchio e copia tutto in quello nuovo. Quindi tecnicamente fa la cosa sensata e non c'é frammentazione.
    2. @AccountTemppp 28 novembre 2025
      @esadecimaleGrazie per la risposta, questo lo sapevo già! io intendo il blocco precedentemente allocato, se ripetiamo realloc tante volte la memoria non viene segmentata? ( chiedo per la mia inesperienza e voglia di imparare )
    3. @esadecimale Autore 28 novembre 2025
      ​@AccountTemppp Assolutamente, le domande sono molto utili! Tu cosa intendi con "il blocco precedente"? Abbiamo una struct fatta da due interi e un char ** data. Quindi abbiamo un array di puntatori. Ora il "blocco" qui potrebbe essere considerato come una istanza di questo array in memoria. Fai dall'indirizzo 0x5 all'indirizzo 0xA. Ora nel momento in cui faccio un realloc per aggiungere, diciamo, altri 5 puntatori, non separo i due blocchi. Quindi lavoro con un singolo blocco. L'allocatore prova ad estendere il blocco già esistente, quindi da 0x5 a 0xA, fino a 0xA + 5. Se non riesce a trovare lo spazio ne alloca un'altro in un luogo nuovo. Quindi non hai un "blocco precedente", perché viene deallocato e gestito nuovamente dall'allocatore, che lo potrà riutilizzare come meglio crede. Se poi intendi che facendo realloc tante volte crei dei "buchi" nella memoria dinamica (heap), c'é da considerare che l'heap è stata proprio fatta per questo, quindi lì non è un problema. L'allocatore è fatto per essere efficiente nel trovare dei nuovi blocchi di memoria. Quindi li parlare di frammentazione della memoria non penso sia corretto. Ha più senso parlare di frammentazione quando la memoria che stai utilizzando è spezzata un po' ovunque nella memoria. Quello è un problema perché ti può portare a non utilizzare in modo efficiente le linee di cache del sistema. Ma il fatto che la memoria heap nel tempo si frammenta non è un problema, perché l'allocatore si mette in mezzo e cerca di rendere il tutto il più efficiente possibile (andando, tra le altre cose, a diminuire la frammentazione)
    4. @AccountTemppp 28 novembre 2025
      @esadecimalegrazie mille ora mi è tutto più chiaro