Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker
DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker
Analizziamo nel dettaglio DJI RS 5, l'ultimo arrivato della famiglia Ronin progettato per videomaker solisti e piccoli studi. Tra tracciamento intelligente migliorato e ricarica ultra rapida, scopriamo come questo gimbal eleva la qualità delle produzioni.
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D è la nuova CPU gaming di riferimento grazie alla 3D V-Cache di seconda generazione e frequenze fino a 5,6 GHz. Nei test offre prestazioni superiori a 9800X3D e 7800X3D, confermando la leadership AMD nel gaming su PC.
Le soluzioni FSP per il 2026: potenza e IA al centro
Le soluzioni FSP per il 2026: potenza e IA al centro
In occasione del Tech Tour 2025 della European Hardware Association abbiamo incontrato a Taiwan FSP, azienda impegnata nella produzione di alimentatori, chassis e soluzioni di raffreddamento tanto per clienti OEM come a proprio marchio. Potenze sempre più elevate negli alimentatori per far fronte alle necessità delle elaborazioni di intelligenza artificiale.
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


DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker DJI RS 5: stabilizzazione e tracking intelligent...
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequen...
Le soluzioni FSP per il 2026: potenza e IA al centro Le soluzioni FSP per il 2026: potenza e IA al ce...
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa AWS annuncia European Sovereign Cloud, il cloud ...
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto Redmi Note 15 Pro+ 5G: autonomia monstre e displ...
Il National Reconnaissance Office statun...
Volkswagen avvia la produzione su CEA: c...
La crisi delle memorie non influenzer&ag...
MoM-z14 è la galassia scoperta da...
Da Sony nuovi display professionali dell...
Com'è fatta una delle e-bike pi&u...
iPhone 16 domina il 2025: ecco la classi...
Huawei a supporto delle startup: potenzi...
Iliad è il miglior operatore di l...
Le pompe di calore parlano italiano: Bon...
Moltbot non è solo un chatbot: ag...
Sinner e Alcaraz fermati dall'arbitro: i...
L'audio-video professionale arriva a MIR...
Musk fa i complimenti alla Cina: nel set...
Agcom ha avviato verifiche sul format 'F...
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: 20:07.


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