Torna indietro   Hardware Upgrade Forum > Software > Programmazione

ASUS Expertbook PM3: il notebook robusto per le aziende
ASUS Expertbook PM3: il notebook robusto per le aziende
Pensato per le necessità del pubblico d'azienda, ASUS Expertbook PM3 abbina uno chassis particolrmente robusto ad un pannello da 16 pollici di diagonale che avantaggia la produttività personale. Sotto la scocca troviamo un processore AMD Ryzen AI 7 350, che grazie alla certificazione Copilot+ PC permette di sfruttare al meglio l'accelerazione degli ambiti di intelligenza artificiale
Test ride con Gowow Ori: elettrico e off-road vanno incredibilmente d'accordo
Test ride con Gowow Ori: elettrico e off-road vanno incredibilmente d'accordo
Abbiamo provato per diversi giorni una new entry del mercato italiano, la Gowow Ori, una moto elettrica da off-road, omologata anche per la strada, che sfrutta una pendrive USB per cambiare radicalmente le sue prestazioni
Recensione OnePlus 15: potenza da vendere e batteria enorme dentro un nuovo design
Recensione OnePlus 15: potenza da vendere e batteria enorme dentro un nuovo design
OnePlus 15 nasce per alzare l'asticella delle prestazioni e del gaming mobile. Ma non solo, visto che integra un display LTPO 1,5K a 165 Hz, OxygenOS 16 con funzioni AI integrate e un comparto foto con tre moduli da 50 MP al posteriore. La batteria da 7.300 mAh con SUPERVOOC 120 W e AIRVOOC 50 W è la ciliegina sulla torta per uno smartphone che promette di offrire un'esperienza d'uso senza alcun compromesso
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 01-06-2009, 16:38   #1
Honik
Member
 
Iscritto dal: Aug 2007
Messaggi: 68
[C] Strutture,liste e puntatori..

Salve a tutti... ho questo codice fornito dal mio professore di fondamenti..

Codice:
typedef struct{
        char titolo[30];
        int video;
        int audio;
        char trama[255];
        } film ;
        
struct StructLista {
       film info;
       struct StructLista *next;
       } ;
       
typedef struct StructLista NodoLista;
typedef NodoLista* Lista;

// Inizializza e azzera la lista passata come parametro
void InizLista(Lista *lis){
     *lis==NULL;
     }               
// Inserisce l'elemeno passato come parametro, in testa
void InserisciInTesta(Lista *lis, film elemento){
     Lista paux;
     paux=malloc(sizeof(NodoLista));
     if(paux==NULL) exit(1);
     paux->info=elemento;
     paux->next=*lis;
     *lis=paux;
     }
// Restituisce la testa della lista
void TestaLista(Lista lis, film *elem){
     if(lis==NULL)exit(1);
     *elem=lis->info;
     }
Mi chiedo la seguente cosa..
definisco un nuovo tipo -> typedef NodoLista* Lista; <- quindi Lista mi punta all'indirizzo del nodo della lista...

Però nella prima funzione (ad esempio) passo come paramentro -> Lista *lis <-.. questo vuol dire che già Lista è un puntatore che associo ad un'altro puntatore (*lis), quindi il parametro non sarà un puntatore ma il suo contenuto interno, infatti poi uso tale puntatore con l'operatore * per settare il suo indirizzo in null... mi chiedo se non è possibile fare lo stesso nel seguente modo

void InizLista(Lista lis){
lis==NULL;
}

in tale modo lis dovrebbe essere già un puntatore.. potreste spiegarmi bene questa situazione??
Honik è offline   Rispondi citando il messaggio o parte di esso
Old 01-06-2009, 18:14   #2
Mesh89
Member
 
Iscritto dal: Dec 2006
Messaggi: 198
Innanzi tutto, == è un operatore di confronto, non di assegnamento. Probabilmente quello che vuoi fare tu è: lis = NULL;

Per quanto riguarda la tua domanda: si, non solo si può fare, ma è anche la via migliore (o meno deviata Spesso in C le strutture dati vengono passate per indirizzo per questioni di performance. Ma questo ovviamente non è il tuo caso, quindi non vedo una ragione di chiedere un puntatore ad un puntatore, invece del puntatore stesso.
Mesh89 è offline   Rispondi citando il messaggio o parte di esso
Old 01-06-2009, 21:39   #3
Honik
Member
 
Iscritto dal: Aug 2007
Messaggi: 68
Quote:
Originariamente inviato da Mesh89 Guarda i messaggi
Innanzi tutto, == è un operatore di confronto, non di assegnamento. Probabilmente quello che vuoi fare tu è: lis = NULL;

Per quanto riguarda la tua domanda: si, non solo si può fare, ma è anche la via migliore (o meno deviata Spesso in C le strutture dati vengono passate per indirizzo per questioni di performance. Ma questo ovviamente non è il tuo caso, quindi non vedo una ragione di chiedere un puntatore ad un puntatore, invece del puntatore stesso.
Si è stato un errore di battitura.. era un'assegnamento!! Comunque, perchè il professore ha scelto quella via usando il doppio puntatore(puntatore di puntatore)??
Quello che volevo chiedere è : il suo modo di passare il parametro il mio sono uguali giusto? un puntatore di puntatore annulla il puntatore stesso, quindi tantovale passare solo un puntatore a nodo ed usarlo senza derefenziamento!

Ultima modifica di Honik : 01-06-2009 alle 21:54.
Honik è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 02:11   #4
Ikon O'Cluster
Registered User
 
Iscritto dal: May 2009
Messaggi: 300
A mio modo di vedere quel typedef copre il fatto che Lista sia in realtà un puntatore. Se tu usassi come argomento formale della funzione il tipo Lista qualcuno a prima vista (senza aver visto il typedef) potrebbe supporre che il passaggio stia avvenendo per valore. Questo lo indurrebbe a credere che l'assegnamento lis = NULL non abbia effetto sull'argomento attuale. Se tu indichi come argomento formale il tipo Lista* allora chi legge sa che maneggiando il contenuto puntato ottiene effetto anche all'esterno della funzione. Io lo interpreterei come un dettaglio di maggiore leggibilità. Anche io l'avrei fatto così, ha una sua logica: se stai passando per puntatore o per riferimento è perchè vuoi che all'esterno vi siano effetti, se passi per valore no. Se nascondi tutto col typedef non stai facendo una bella cosa! Chi deve leggere il tuo codice, vuole leggerlo non decifrarlo!
Ikon O'Cluster è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 11:20   #5
Honik
Member
 
Iscritto dal: Aug 2007
Messaggi: 68
Non avevo considerato questo aspetto!! Sicuramente, visto che le funzioni dovrebbe essere scatole chiuse, io (client) non mi devo preoccupare tanto del loro contenuto.. il concetto dovrebbe essere questo
Honik è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 15:09   #6
Honik
Member
 
Iscritto dal: Aug 2007
Messaggi: 68
Ho trovato non poche difficoltà a capire quel codice.. ho provato a "revisionarlo" a modo mio...
Ecco i due file:

liste.c
Codice:
typedef struct{
        char titolo[30];
        int video;
        int audio;
        char trama[255];
        } film ;
        
struct StructLista {
       film info;
       struct StructLista *next;
       } ;
       
typedef struct StructLista NodoLista;


// Inizializza e azzera la lista passata come parametro
void InizLista(NodoLista *lis){
     lis=NULL;
     if(lis==NULL) printf("\n\nLista inizializzata\n\n");
     }               
// Inserisce l'elemeno passato come parametro, in testa
void InserisciInTesta(NodoLista *lis, film elemento){
     NodoLista *paux;
     paux=malloc(sizeof(NodoLista));
     if(paux==NULL) exit(1);
     paux->info=elemento;
     paux->next=lis;
     lis=paux;
     }
// Restituisce la testa della lista
void TestaLista(NodoLista *lis, film *uelem){
     if(lis==NULL)printf("errore.. lista vuota!");
     *uelem=lis->info;
     }
// Visualizza la lista
void VediLista(NodoLista *lis){
     while (lis!=NULL){
           printf("%s", lis->info.titolo);           
           }
     
     }
main.c

Codice:
#include <stdio.h>
#include <stdlib.h>
#include "liste.c"

#define MENU 200
#define OUT 255

void AcqElemento(film elem){
     printf("Titolo film: ");
     scanf("%s", elem.titolo);
     printf("\nInsersci trama: ");
     scanf("%s", elem.trama);
     printf("\nQualità video: ");
     scanf("%d", &elem.video);
     printf("\nQualità audio: ");
     scanf("%d", &elem.audio);
     
     }

main(){
       NodoLista *plist;
       film elem;
       film *uelem;
       int scelta=MENU;
       while (scelta==MENU){
             printf("\n\n\t\t################-> Gestione Film <-################");
             printf("\n\n 1. Crea la lista");
             printf("\n\n 2. Inserisci in testa un'elemento");{}
             printf("\n\n 3. Guarda il primo elemento in testa");
             printf("\n\n 4. Guarda tutta la lista");
             printf("\n\n 0. Esci");
             printf("\n\n\n\t\t\t La tua scelta: ");
             scanf("%d", &scelta);
             switch(scelta){
                            case 0:
                                 scelta=OUT;
                                 break;
                            case 1:
                                 InizLista(plist);
                                 scelta=MENU;
                                 break;     
                            case 2:
                                 AcqElemento(elem);
                                 InserisciInTesta(plist, elem);
                                 scelta=MENU;
                                 break;
                            case 3:
                                 TestaLista(plist, uelem);
                                 scelta=MENU;
                                 break;     
                            case 4:
                                 VediLista(plist);
                                 scelta=MENU;
                                 break;    
                            
                            }
             
             }
       
       }
Però ho dei problemi, nella visualizzazione della lista (solo titolo per ora)e nella testa.. magari mi sfugge qualcosa di importante.. sapreste indicarmelo?
GRAZIE
Honik è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 18:25   #7
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Se te l'ha dato un professore quel codice allora stiamo messi male...

Ci sono alcune perle tipo questa:
Codice:
     if(paux==NULL) exit(1);
per le quali non so se ridere o piangere.

ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 18:29   #8
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da Honik Guarda i messaggi
Codice:
#include <stdio.h>
#include <stdlib.h>
#include "liste.c"
Quello non farlo mai, già a partire da progetti che vadano appena oltre il codice di test per una lista ti può creare casini che non vuoi, credimi.

Piuttosto metti l'implementazione del codice in un file C separato che compilerai a parte, e le definizioni dei tipi e delle costanti e i prototipi delle funzioni li metterai in un header da includere in giro dove ti serve.

ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 18:54   #9
Honik
Member
 
Iscritto dal: Aug 2007
Messaggi: 68
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Quello non farlo mai, già a partire da progetti che vadano appena oltre il codice di test per una lista ti può creare casini che non vuoi, credimi.

Piuttosto metti l'implementazione del codice in un file C separato che compilerai a parte, e le definizioni dei tipi e delle costanti e i prototipi delle funzioni li metterai in un header da includere in giro dove ti serve.

ciao
Cosa non va in quella "perla"?mi saresti d'aiuto se mi spiegassi l'errore!
Honik è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 18:57   #10
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Un po' di considerazioni su liste.c:

Codice:
struct StructLista {
       film info;
       struct StructLista *next;
       } ;
Io definirei info come un film *, non un film e basta: film è infatti una struttura (un "bloccone" di memoria) che non può essere "assegnata" direttamente, ma per farlo ti appoggi ad una memcpy() (lento).

Codice:
typedef struct StructLista NodoLista;
Per lo stesso motivo di prima, un nodo della lista potresti volerlo definire piuttosto come un puntatore alla struttura (quindi uno struct StructLista *), non come una struttura.

Codice:
void InizLista(NodoLista *lis){
     lis=NULL;
     if(lis==NULL) printf("\n\nLista inizializzata\n\n");
     }
In C tutti i parametri sono passati per valore, per avere un passaggio per riferimento devi ricorrere ai puntatori. In questa funzione stai ricevendo un puntatore ad un nodo della lista, e poi... lo sovrascrivi con un NULL. Pensaci: hai cambiato l'indirizzo contenuto in lis (sovrascrivendone il valore), non il contenuto della memoria che sta nell'indirizzo indicato da lis. Può sembrare intricato, ma se capisci bene questa differenza sei a buon punto nel saper lavorare coi puntatori.
Per farlo correttamente avresti dovuto usare:
Codice:
(*lis) = NULL;
if (*lis == NULL) /* ... */
In questo modo sì che avresti sovrascritto la memoria puntata da lis, non lis stesso (che è passato per valore, le modifiche non sarebbero state propagate alla funzione chiamante). Ma attento, anche così non avrebbe funzionato: perché? Te lo lascio come esercizio. :P

Codice:
void InserisciInTesta(NodoLista *lis, film elemento){
     NodoLista *paux;
     paux=malloc(sizeof(NodoLista));
     if(paux==NULL) exit(1);
     paux->info=elemento;
     paux->next=lis;
     lis=paux;
     }
Quel "exit(1)" che termina l'applicazione senza dire nulla è un po' brutto, soprattutto se fatto in una funzione di utilità che non può (e non deve) effettuare alcun cleanup; io piuttosto preferirei restituire un codice di errore al chiamante, il quale vedrà come preferisce gestire la condizione imprevista.

Infine, riscrivi l'indirizzo di lis senza cambiare i contenuti della memoria a cui punta, come prima dicevo.

Codice:
void VediLista(NodoLista *lis){
     while (lis!=NULL){
           printf("%s", lis->info.titolo);           
           }
     }
Qui non entrerai per niente nel ciclo se la lista è nulla (il che è esattamente quanto ti aspetti), ma invece se la lista punta a qualcosa il ciclo risulterà infinito (non modifichi mai lis, non potrà mai diventare NULL se non lo è fin dall'inizio).

ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!

Ultima modifica di DanieleC88 : 04-06-2009 alle 01:21. Motivo: Rimossi un po' di avvertimenti inutili, in effetti Mesh89 mi ricorda che l'assegnazione di strutture è standard.
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 19:01   #11
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da Honik Guarda i messaggi
Cosa non va in quella "perla"?mi saresti d'aiuto se mi spiegassi l'errore!
L'ho appena fatto, ma il post era un po' lunghetto, non sono mica Flash. :P (e meno male, al limite preferirei essere JavaFX... battuta tristissima )

Non ti offendere eh, cerco di aiutare, non di sfottere.
ciao
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 19:30   #12
Mesh89
Member
 
Iscritto dal: Dec 2006
Messaggi: 198
In effetti rileggendo il mio post mi rendo conto di aver scritto una hazzata

Come ha correttamente spiegato Daniele, tu stai si passando un puntatore, ma per valore, non per indirizzo; quindi le modifiche ad essp non si vedranno al di fuori della funzione.

Conosci il passaggio di parametri per indirizzo? A mio avviso sarebbe il modo più pulito di fare la cosa. inoltre noto che hai lo stesso problema nell'ultima riga della funzione di inserimento.

@Daniele: ho sempre saputo che struct = struct e memcpy fossero equivalenti. Perchè la prima via è sbagliata?
Mesh89 è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 19:59   #13
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da Mesh89 Guarda i messaggi
@Daniele: ho sempre saputo che struct = struct e memcpy fossero equivalenti. Perchè la prima via è sbagliata?
Infatti sono equivalenti (però dal C90 in poi, se non erro, nel C "K&R" non mi sembra ci sia l'assegnazione di strutture, qualcuno mi corregga se sparo boiate!), e infatti è proprio per quello che non mi piace.

Il fatto è che se ti abitui che puoi "assegnare" una struttura la prendi come fosse un'operazione elementare, quando non è così (è in effetti una copia binaria di un blocco di memoria più o meno grande). Per piccole strutture non è un grosso problema, ma chi ti impedisce questo, per esempio?
Codice:
struct s_MyBlob
{
    short nIndex;
    char szName[512];
    char szBlobData[2097152];
};

int main()
{
    struct s_MyBlob a, b;
    int count;

    memset(&a, 0, sizeof(struct s_MyBlob));
    memset(&b, 0, sizeof(struct s_MyBlob));

    for (count = 0; count < 10000; ++count)
    {
        ++(b.nIndex);
        a = b;
    }

    printf("Terminato.");
    return 0;
}
In questo codice ci sono, "nascoste", 10000 memcpy() di 2097152 + 512 + 2 byte di dati = più o meno 2MB (se non di più per via del padding) ognuna, ovvero oltre 20000MB di dati spostati a vuoto.

Se invece fosse stato:
Codice:
struct s_MyBlob
{
    short nIndex;
    char szName[512];
    char szBlobData[16777216];
};

typedef struct s_MyBlob *p_MyBlob;

int main()
{
    p_MyBlob a, b;
    int count;

    a = (p_MyBlob) malloc(sizeof(struct s_MyBlob));

    if (!a)
    {
        fprintf(stderr, " [**] Allocazione di a fallita.\n");
        return 1;
    }

    memset(a, 0, sizeof(struct s_MyBlob));

    b = (p_MyBlob) malloc(sizeof(struct s_MyBlob));

    if (!b)
    {
        fprintf(stderr, " [**] Allocazione di b fallita.\n");
        return 1;
    }

    memset(b, 0, sizeof(struct s_MyBlob));

    for (count = 0; count < 10000; ++count)
    {
        p_MyBlob c;

        ++(b->nIndex);
        c = b;
    }

    free(a);
    free(b);

    printf("Terminato.");
    return 0;
}
ci sarebbero state 10000 assegnazioni semplicemente di un puntatore (tipicamente di 4 byte), quindi 40000 byte = più o meno 39MB di dati spostati a vuoto.

Sì, lo so, sono integralista, non ci posso fare niente.

EDIT: tanto per curiosità ho voluto fare un confronto sulla mia macchina (che monta un AMD Athlon™ 64 X2 5200+ con 4GB di RAM, forse non il top ma direi che è abbastanza veloce), il primo programmino con l'assegnazione impiega 16 secondi a terminare, il secondo 100 millisecondi... circa 160 volte più veloce, mica male.
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!

Ultima modifica di DanieleC88 : 02-06-2009 alle 22:28. Motivo: Avevo fatto un errore da principante, il Python mi sta deviando...
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 02-06-2009, 20:10   #14
DanieleC88
Senior Member
 
L'Avatar di DanieleC88
 
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
Quote:
Originariamente inviato da DanieleC88 Guarda i messaggi
Per piccole strutture non è un grosso problema, ma chi ti impedisce questo, per esempio?
Errata corrige: me lo impedisce la dimensione dello stack.
In effetti c'ho buttato 32MB di memoria sullo stack, chiaramente il programmino va in segmentation fault.
__________________

C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai!
DanieleC88 è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2009, 01:36   #15
Ikon O'Cluster
Registered User
 
Iscritto dal: May 2009
Messaggi: 300
Quote:
Originariamente inviato da Honik Guarda i messaggi
Non avevo considerato questo aspetto!! Sicuramente, visto che le funzioni dovrebbe essere scatole chiuse, io (client) non mi devo preoccupare tanto del loro contenuto.. il concetto dovrebbe essere questo
Le funzioni sono scatole chiuse finchè non devi metterci le mani dentro Non si programma solo per chi usa, ma anche per chi modifica
Ikon O'Cluster è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


ASUS Expertbook PM3: il notebook robusto per le aziende ASUS Expertbook PM3: il notebook robusto per le ...
Test ride con Gowow Ori: elettrico e off-road vanno incredibilmente d'accordo Test ride con Gowow Ori: elettrico e off-road va...
Recensione OnePlus 15: potenza da vendere e batteria enorme dentro un nuovo design   Recensione OnePlus 15: potenza da vendere e batt...
AMD Ryzen 5 7500X3D: la nuova CPU da gaming con 3D V-Cache per la fascia media AMD Ryzen 5 7500X3D: la nuova CPU da gaming con ...
SONY BRAVIA 8 II e BRAVIA Theatre System 6: il cinema a casa in formato compatto SONY BRAVIA 8 II e BRAVIA Theatre System 6: il c...
Super sconto sulla GoPro HERO13 Black: i...
Nintendo: ecco le prime immagini del fil...
NIO ha una super batteria da 1.000 km, m...
Primo crollo di prezzo: iPhone 17 Pro Ma...
Una super offerta su Amazon: la scopa el...
Xiaomi 15 Ultra crolla di prezzo su Amaz...
Disney punta sull'IA? L'animatrice di Th...
Il processo produttivo a 2 nanometri di ...
Su Amazon DREAME e MOVA Ultra fanno pazz...
GlobalFoundries fa shopping a Singapore ...
3 smartphone in sconto Black Friday, Xia...
POCO conferma l'arrivo della serie F8: c...
HONOR 500: confermata data di lancio e d...
iPhone Fold non è ancora pronto? ...
Nuovo smartphone in arrivo da OnePlus: t...
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: 10:02.


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