Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione Nothing Phone (4a) Pro: finalmente in alluminio, ma dal design sempre unico
Recensione Nothing Phone (4a) Pro: finalmente in alluminio, ma dal design sempre unico
Nothing Phone (4a) Pro cambia pelle: l'alluminio unibody sostituisce la trasparenza integrale, portando una solidità inedita. Sotto il cofano troviamo uno Snapdragon 7 Gen 4 che spinge forte, mentre il display è quasi da top dig amma. Con un teleobiettivo 3.5x e la Glyph Matrix evoluta, è la prova di maturità di Carl Pei. C'è qualche compromesso, ma a 499EUR la sostanza hardware e la sua unicità lo rendono un buon "flagship killer" in salsa 2026
WoW: Midnight, Blizzard mette il primo, storico mattone per l'housing e molto altro
WoW: Midnight, Blizzard mette il primo, storico mattone per l'housing e molto altro
Con Midnight, Blizzard tenta il colpaccio: il player housing sbarca finalmente su Azeroth insieme a una Quel'Thalas ricostruita da zero. Tra il dramma della famiglia Ventolesto e il nuovo Prey System, ecco com'è la nuova espansione di World of Warcraft
Ecovacs Goat O1200 LiDAR Pro: la prova del robot tagliaerba con tagliabordi integrato
Ecovacs Goat O1200 LiDAR Pro: la prova del robot tagliaerba con tagliabordi integrato
Nuova frontiera per i robot tagliaerba, con Ecovacs GOAT O1200 LiDAR Pro che riconosce l'ambiente in maniera perfetta, grazie a due sensori LiDAR, e dopo la falciatura può anche rifinire il bordo con il tagliabordi a filo integrato
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 22-01-2014, 10:17   #1
sharkkk
Member
 
L'Avatar di sharkkk
 
Iscritto dal: Oct 2013
Messaggi: 158
[C] liste dinamiche

Passo passo sto cercando di comprendere a fondo l'utilizzo dei puntatori e mi sono imbattuto in questo codice elementare.
Ma cosa fa esattamente passo per passo?

Codice:
typedef struct lista{
       int val;
       struct lista* next;
       } LIST;

int main(){...

    LIST* element;
     element = (LIST*)malloc(sizeof(LIST));


LIST* element;
- Creo un puntatore di tipo LIST, che ha un valore casuale e che non punta a nulla.

element = (LIST*)malloc(sizeof(LIST));
- malloc(sizeof(LIST)) alloca tanta memoria per element tanta quanto ne occupa il tipo LIST
- element = (LIST*)malloc(sizeof(LIST)); fa un cast al tipo LIST* perchè element è di tipo LIST*

Le domande sono:
a) Quello che ho scritto è giusto?
b) Ma in quale punto creo una nuova istanza di tipo LIST in cui posso già accedere agli elementi della struttura?
c) perche devo fare la malloc se faccio LIST* element? con questa dichiarazione element non è già grande quanto LIST?


p.s.
LIST* testa;
testa = NULL;

testa = NULL; imposta tutti gli elementi della struttura a NULL oppure il puntatore non punta piu ad una struttura ma solo a NULL?



grazie a chiunque mi aiuterà
sharkkk è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 10:37   #2
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Ciao,
a) la descrizione che hai dato è giusta;
b) la domanda non ha una risposta soddisfacente, nel senso che LIST è una struttura, ovvero una definizione di come sono organizzati i dati in memoria, il concetto di istanza è legato alla programmazione ad oggetti, anche se spesso viene utilizzato in modo improprio. La funzione malloc alloca la memoria necessaria, poi, facendo il casting del puntatore, istruisci il programma a trattare quell'area di memoria come se vi si trovasse una struttura LIST.
c) LIST* alloca solo lo spazio per un puntatore, lo spazio per la struttura va allocato separatamente, o con malloc, oppure dichiarando la variabile con LIST (senza asterisco), però tieni presente che sono due operazioni diverse e non sempre interscambiabili (la prima alloca nell'heap, la seconda sullo stack).

In fine, testa = NULL imposta la variabile testa - che è un puntatore - a NULL; se prima puntava a qualche elemento, questo resterà allocato in memoria, disperso (ma non diventa NULL, e mai potrebbe farlo, e solo memoria).
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 10:42   #3
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Ora che ci penso, sarebbe meglio dire che il programma è già istruito a trattare element come una LIST; assegnando a element un'indirizzo, indichi al programma dove si trova la memoria da utilizzare quando accedi ai campi di element.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 11:04   #4
sharkkk
Member
 
L'Avatar di sharkkk
 
Iscritto dal: Oct 2013
Messaggi: 158
grazie daniel

quindi scrivere
LIST* element; oppure void* element ipoteticamente a questo livello sarebbero la stessa cosa visto che non stanno puntando a nulla?

penso di aver capito che il primo puntatore, con la malloc, eredita la dichiarazione di LIST, tramite cui posso accedere agli elementi della struttura (con il dovuto cast).

pero ho visto un esercizio di un professore e lui senza fare la malloc o la new, in una funzione, accede ai campi di un puntatore a struttura. (il programma funziona correttamente, C++)

Codice:
//Funzione che crea una lista di n interi prendendoli da tastiera
lista* crea_lista(int n){
	lista *l,*aux;
    lista *root=NULL;
    cout<<"Inserire "<<n<<" interi crescenti \n";
    for (int i=0; i<n; i++) {
        aux= new lista;
        if (root==NULL)
        	root=aux;
        else
        	l->next=aux;
        l=aux;
        cin>>l->val;
        l->next=NULL;
    }
    return (root);
}
aux correttamente viene allocato ma l no, eppure lui accede al campo next (l->next=aux;)
come fa?
sharkkk è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 11:17   #5
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
LIST* element e void* element hanno lo stesso effetto in termini di memoria, ovvero allocano 4 byte (8 su sistemi a 64 bit) per un puntatore, naturalmente il compilatore si arrabbia di brutto se dichiari element come void* e poi scrivi element.next

malloc alloca solo memoria, il casting in questo caso serve per evitare che un programmatore inesperto o distratto faccia in modo inconsapevole assegnazioni tra dati di tipo diversi. Il compilatore tratta element come LIST anche se non gli assegni un indirizzo allocato con malloc. Ovviamente questo comporta l'accesso ad aree di memoria protette o peggio, dove sono conservati altri dati, facendo crashare il programma. L'assegnazione di un indirizzo valido ad element serve per riservargli uno spazio che non sia già utilizzato o che potrebbe essere utilizzato in futuro.

aux= new lista; alloca spazio per un elemento lista e assegna l'indirizzo ad aux;
l=aux; assegna ad l lo stesso indirizzo di aux, pertanto l punta alla stessa area di memoria allocata in precedenza;
if (root==NULL) questa condizione assicura che l'accesso al campo next attraverso il puntatore l avvenga solo alla seconda iterazione, per cui l è già stato inizializzato con un indirizzo valido.

Ultima modifica di Daniels118 : 22-01-2014 alle 11:20.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 11:29   #6
sharkkk
Member
 
L'Avatar di sharkkk
 
Iscritto dal: Oct 2013
Messaggi: 158
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
aux= new lista; alloca spazio per un elemento lista e assegna l'indirizzo ad aux;
l=aux; assegna ad l lo stesso indirizzo di aux, pertanto l punta alla stessa area di memoria allocata in precedenza;
if (root==NULL) questa condizione assicura che l'accesso al campo next attraverso il puntatore l avvenga solo alla seconda iterazione, per cui l è già stato inizializzato con un indirizzo valido.
mi ero lasciato sfuggire che quell'else avveniva nella prima iterazione


credo di aver capito per bene tutto anche se ora con questa cosa mi hai mandato in panico

Quote:
Il compilatore tratta element come LIST anche se non gli assegni un indirizzo allocato con malloc.
se la malloc è facoltativa, quindi LIST* element basterebbe da solo per ereditare la dichiarazione della struttura (e farci tutte le operazioni)?
a questo punto void* element farebbe la medesima cosa?



p.s.
un mio professore tempo fa disse che il primo elemento di un array, il primo elemento di una struttura, una funzione sono in realtà dei puntatori, è esatto?
anche le classi?

Ultima modifica di sharkkk : 22-01-2014 alle 11:40.
sharkkk è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 11:42   #7
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
malloc non è facoltativa, semplicemente se non la usi il compilatore non ti da errore, ma quando esegui il programma ottieni risultati imprevedibili e comunque non desiderabili. Al posto di malloc potresti utilizzare new, ma una delle due la devi utilizzare comunque.
C'è una terza possibilità, ovvero quella di allocare un LIST invece di un LIST*, ma non è la stessa cosa rispetto agli altri due metodi. Se ti interessa approfondire questo aspetto chiedilo esplicitamente.

LIST* element; basta a far capire al compilatore che element è un puntatore ad un area di memoria e che element ha dei campi definiti come indicato in "typedef struct lista".
LIST* element; basta anche ad allocare lo spazio sufficiente per un puntatore, che nel nostro sorgente chiameremo element.
LIST* element; non alloca la memoria necessaria per una struttura di tipo LIST; per quello bisogna usare malloc o new.
void* element; fa la stessa cosa di LIST* element; ma poi il compilatore non saprebbe che element ha dei campi chiamati val e next, quindi ti darebbe errore se provassi ad accedervi tramite element.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 11:58   #8
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Per puntatore si intende una variabile che non contiene direttamente un dato utile all'elaborazione, ma indica il luogo dove si trova questo dato (o un altro puntatore).
Qualunque dato risiede in memoria, e pertanto ha un indirizzo. Tu puoi definire un puntatore e farlo puntare a qualunque indirizzo. Puoi anche valorizzare un puntatore in modo che punti nel mezzo di una struttura.

Quello che probabilmente ti ha detto il tuo professore è che:
il puntatore ad un array punta al primo elemento in quell'array;
il puntatore ad una struttura punta al primo campo in quella struttura;
il puntatore ad una stringa punta al primo carattere in quella stringa.

Una funzione è una porzione di codice che risiede in memoria, quindi ha un indirizzo, di conseguenza un puntatore potrebbe puntare ad una funzione. I puntatori a funzioni vengono utilizzati per chiamare le funzioni dinamicamente; l'utilizzo più comune ed ignorato dei puntatori a funzione in ambiente windows è la registrazione della callback per la gestione dei messaggi, indispensabile per la creazione delle finestre.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 12:02   #9
sharkkk
Member
 
L'Avatar di sharkkk
 
Iscritto dal: Oct 2013
Messaggi: 158
Quote:
Originariamente inviato da Daniels118 Guarda i messaggi
malloc non è facoltativa, semplicemente se non la usi il compilatore non ti da errore, ma quando esegui il programma ottieni risultati imprevedibili e comunque non desiderabili. Al posto di malloc potresti utilizzare new, ma una delle due la devi utilizzare comunque.
C'è una terza possibilità, ovvero quella di allocare un LIST invece di un LIST*, ma non è la stessa cosa rispetto agli altri due metodi. Se ti interessa approfondire questo aspetto chiedilo esplicitamente.

LIST* element; basta a far capire al compilatore che element è un puntatore ad un area di memoria e che element ha dei campi definiti come indicato in "typedef struct lista".
LIST* element; basta anche ad allocare lo spazio sufficiente per un puntatore, che nel nostro sorgente chiameremo element.
LIST* element; non alloca la memoria necessaria per una struttura di tipo LIST; per quello bisogna usare malloc o new.
void* element; fa la stessa cosa di LIST* element; ma poi il compilatore non saprebbe che element ha dei campi chiamati val e next, quindi ti darebbe errore se provassi ad accedervi tramite element.
ora mi hai tolto ogni dubbio.

ho letto, e credo di aver capito che es. LIST element non si usa molto nei casi in cui abbiamo bisogno di usare e rimuovere strutture, perche occuperemmo memoria inutile sullo stack, mentre tramite LIST* element dinamicamente posso allocare/liberare lo spazio occupato in memoria (nello heap invece che sullo stack) dalla struttura

Ultima modifica di sharkkk : 22-01-2014 alle 12:05.
sharkkk è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 12:22   #10
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Una precisazione: dichiarare una variabile (o un puntatore) ha sempre effetti diversi a seconda che lo si faccia in una funzione o all'esterno.
Nel primo caso lo spazio per la variabile viene allocato nello stack e deallocato all'uscita dalla funzione: se la funzione non viene mai richiamata, quella variabile non occuperà mai spazio; nel caso di funzioni ricorsive la "stessa" variabile può essere allocata più volte contemporaneamente in memoria.
Nel secondo caso, la variabile finisce nell'area dati, che si trova fisicamente nel file eseguibile e quindi contribuisce alle sue dimensioni; queste variabili esistono per tutta l'esecuzione del programma, anche se non vengono utilizzate.

Il motivo principale per cui non vediamo spesso strutture allocate direttamente sullo stack è che esso è un'area abbastanza piccola e allocarvi una struttura (che può avere anche molti campi) può facilmente saturarlo, producendo un errore di stack overflow. Per lo stesso motivo array con molti elementi vengono sempre allocati con malloc invece che dichiararli con la dimensione tra parentesi quadre.
Ci sono poi delle vere e proprie esigenze, come far persistere la variabile all'uscita di una funzione; in questo caso è d'obbligo l'allocazione nell'heap, perchè lo stack viene sempre liberato al return.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 12:30   #11
sharkkk
Member
 
L'Avatar di sharkkk
 
Iscritto dal: Oct 2013
Messaggi: 158
a questo punto allora daniele la domanda è d'obbligo, lo stack generalmente che dimensioni ha?

immaginandosi un giorno di trovarsi davanti ad un progetto importante, presumo che questa domanda sia particolarmente importante.

la sua dimensione dipende dalla macchina, è possibile aumentare lo spazio di memoria riservato allo stack, come è possibile sapere la sua dimensione?
sharkkk è offline   Rispondi citando il messaggio o parte di esso
Old 22-01-2014, 13:16   #12
Daniels118
Senior Member
 
L'Avatar di Daniels118
 
Iscritto dal: Jan 2014
Messaggi: 852
Parlando di PC, lo stack è parte della memoria e per questo può essere dimensionato dal programma stesso.
Nei sistemi Windows la dimensione dello stack per il thread principale di un programma è specificata nell'header del file eseguibile e può essere modificata inserendo gli opportuni parametri in fase di link; la dimensione predefinita è 1 MB, che è più che sufficiente anche per progetti importanti, basta che non allochi strutture enormi sullo stack. Per i thread secondari avviati con CreateThread è possibile specificare una dimensione diversa o quella predefinita.

Per i sistemi Unix non so, ma suppongo ci sia qualcosa di simile.

Per completezza aggiungo che molti microcontroller hanno uno stack hardware che ovviamente non può essere ingrandito.
Daniels118 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Recensione Nothing Phone (4a) Pro: finalmente in alluminio, ma dal design sempre unico Recensione Nothing Phone (4a) Pro: finalmente in...
WoW: Midnight, Blizzard mette il primo, storico mattone per l'housing e molto altro WoW: Midnight, Blizzard mette il primo, storico ...
Ecovacs Goat O1200 LiDAR Pro: la prova del robot tagliaerba con tagliabordi integrato Ecovacs Goat O1200 LiDAR Pro: la prova del robot...
Recensione Samsung Galaxy S26+: sfida l'Ultra, ma ha senso di esistere? Recensione Samsung Galaxy S26+: sfida l'Ultra, m...
Zeekr X e 7X provate: prezzi, autonomia fino a 615 km e ricarica in 13 minuti Zeekr X e 7X provate: prezzi, autonomia fino a 6...
La Corea del Sud taglia fuori i bus elet...
GoPro taglia ancora: licenziato il 23% d...
Muse S Athena: la fascia che ti legge ne...
PS5 Pro e PSSR 2.0: tutti i giochi compa...
Dimensity 9600 Pro promette prestazioni ...
BMW i7 2026 adotta celle cilindriche Gen...
Cyberpunk 2077 si aggiorna su PS5 Pro co...
Valve porta Steam Link su Vision Pro per...
Google Maps: ufficiali 3 novità c...
TikTok punta tutto sull'Europa: un milia...
OnePlus Nord 6 ufficiale: arriva con una...
Google lancia di nascosto un'app AI che ...
Sony lancia The Playerbase per inserire ...
WhatsApp si aggiorna con una nuova app c...
Windows 11 23H2, ricerca nel menu Start ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 14:34.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v