Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Dark Perk Ergo e Sym provati tra wireless, software via browser e peso ridotto
Dark Perk Ergo e Sym provati tra wireless, software via browser e peso ridotto
be quiet! debutta nel settore mouse da gaming con Dark Perk Ergo e Dark Perk Sym: due modelli gemelli per specifiche, con polling rate di 8.000 Hz anche in wireless, sensore PixArt PAW3950 da 32.000 DPI e autonomia dichiarata fino a 110 ore. Nel test, a 8.000 Hz si arriva a circa 30 ore reali, con ricarica completa in un'ora e mezza
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.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 12-08-2009, 15:47   #1
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
[C] È più efficace passare ritornare una struct o sfruttare le variabili d'ambiente ?

Come da titolo,

ho bisogno di far ritornare diversi parametri da una funzione (che li definisce), affinchè possano essere eventalmente passati alle altre funzioni che richiedano uno o più di questi parametri. Per utilizzare una soluzione elegante ( e facilmente mantenibile ) voglio evitare di definire numerose variabili globali sparse negli header files, ma pensavo alla definizione di una struct che li contenga tutti.

Non posso che chiedermi, se invece convenga (in rapporto prestazioni/comodità) accedere alla lettura/scrittura di variabili d'ambiente.
Probabilmente dovrei valutare quante volte mi servono questi parametri nel programma e decidere di conseguenza...

Poichè molte funzioni avranno bisogno (ad ogni chiamata) di ricevere i corretti parametri, questo implicherebbe dover sempre passare i valori della struct (o tramite puntatore, o tutta la struct), oppure accedere ogni volta in lettura alla variabile d'ambiente.

Secondo voi cosa converebbe usare (in una soluzione generica, ovvio che poi nel caso specifico si può dover sacrificare qualcosa) ?
Se possibile (proprio per la genericità del caso) vorrei che mi spiegaste anche i motivi di una scelta o dell'altra.

Un esempio in peudocodice (molto grezzo e banale) che ipotizza la struct:
Codice:
funzione main:
 struct = funzione_che_ritorna_i_valori;
 chiamata_a_funzione#1(struct);
 chiamata_a_funzione#2(struct);
 // .... etc etc
Mille grazie,

buona giornata.
Ps. perdonate il titolo inesatto, ho dimenticato di togliere la parola "passare".
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 13-08-2009, 19:49   #2
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12936
IMHO basta far ritornare semplicemente un puntatore ad una struct precedentemente allocata nell'heap.

Quindi ti mantieni una struct nell'heap (visto che a quanto ho capito questa struct dev'essere globale) e passi i puntatori all'occorrenza.

Codice:
typedef struct pippo {
    // definisci la tua struttura
} Pippo;

main() {

   Pippo* prova = calloc(1, sizeof(Pippo)); // calloc azzera anche la struttura

   funzione1(prova);
   funzione2(prova);
}

Ultima modifica di WarDuck : 13-08-2009 alle 19:53.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 13-08-2009, 21:26   #3
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Quote:
Originariamente inviato da WarDuck Guarda i messaggi
IMHO basta far ritornare semplicemente un puntatore ad una struct precedentemente allocata nell'heap.

Quindi ti mantieni una struct nell'heap (visto che a quanto ho capito questa struct dev'essere globale) e passi i puntatori all'occorrenza.

Codice:
typedef struct pippo {
    // definisci la tua struttura
} Pippo;

main() {

   Pippo* prova = calloc(1, sizeof(Pippo)); // calloc azzera anche la struttura

   funzione1(prova);
   funzione2(prova);
}
Grazie mille per la risposta.
In effetti, cercando sul web un po' a fondo ho trovato questa soluzione, ma non così chiara (leggevo giusto: passare un puntatore alla struct) e mi è sembrata da subito adatta come soluzione al mio quesito. Ma ti ringrazio per la esposizione e lo snippet che illustra il suo utilizzo (e soprattuto per il fatto che mi hai indicato di usare la calloc, che altrimenti, probabilmente avrebbe richiesto un ulteriore topic in seguito ).

Per ora mi affiderò a questa soluzione,

grazie e buona serata!
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 13-08-2009, 21:37   #4
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12936
Prego, di nulla...
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 14-08-2009, 21:06   #5
mr_hyde
Senior Member
 
Iscritto dal: Nov 2005
Città: Genova
Messaggi: 937
Io personalmente preferisco evitare il piu' possibile le variabili globali.
Preferirei una cosa del tipo
Codice:
typedef struct myStruct
{
  unsigned short bIsInitialized;
  int                 theInt;
  float              theFloat;
} myStructType;

/* esempio di funzione che usa la struttra SOLO in input */
int myFunction(const myStructType* pStruct)
{
  /* controllo puntatore (MAI pensare che un puntatore e' sicuramente valido) */
  if (!pStruct) return -1;

  /* controllo su campo correttezza struttura */
  if (!pStruct->bIsInitialized) return -2;

  /* fai qualcosa con pStruct */
  printf("int = %d float = %f\n", pStruct->theInt, pStruct->theFloat);
    
  return 0; 
}

/* esempio di funzione che usa la struttra in input/output */
void myFunctionBis(myStructType* pStruct)

/* altro esempio scemo */
int initMyStruct(myStuctType* pStruct)
{
  /* controllo puntatore (MAI pensare che un puntatore e' sicuramente valido) */
  if (!pStruct) return -1;

  if (qualche_altra_condizione_di_errore) return -10;

  /* inizializzo tutto a 0 */
  memset(pStruct, 0x0, sizeof(myStructType));

  /* popolo quello che mi interessa */
  pStruct->theInt = 12;
  pStruct->theFloat = 123.41f;

  /* dico che il contenuto della struttura e' inizializzato / valido */
  pStruct->bIsInitialized = 1;

  return 0;
}

int main(int argc, char** argv)
{
  /* instanzio la mia struttura vuota */
  myStructType theStruct;

  /* dove memorizzare risultato operazioni */
  short int result = 0;

  /* chiamo la sua funzione di inizializzazione */
  result = initMyStruct(&theStruct);

  /* a seconda del risultato faccio diverse operazioni */
  if (result != 0)
  {
    /* gestisco l'errore in qualche modo */
    ...

    return 1;
  }

  /* uso la struttura */
  result = myFunction(&theStruct);

  ...

  return 0;
}
In questo modo:
1) ho evitato var globali che sono il male assoluto per i programmatori (dopo qualche sessione di debug su progetti grossi con variabili globali, alla ricerca della funzione che le ha impostate in modo errato, capirai il perche')
2) ho evitato allocazioni (perche' complicarsi la vita se non serve? Altra cosa: la calloc in genere e' usata per gli array, per allocare un'unica struttura in genere si usa la malloc)
3) nota poi l'uso di una variabile di "check" (bIsInitialized) per vedere se la struttura ha un contenuto valido oppure no (questo e' un esempio scemo, tuttavia in cose "grosse" puo' far comodo una variabile di check)
4) (e non mi stanchero' mai di ripeterlo) controllare SEMPRE i parametri in input, specialmente i puntatori.

Ciao,
Mr Hyde
__________________
MacMini Late 2009/MacMini 2018

Ultima modifica di mr_hyde : 14-08-2009 alle 21:34.
mr_hyde è offline   Rispondi citando il messaggio o parte di esso
Old 14-08-2009, 23:07   #6
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Wow...

....

son rimasto senza parole O.O".
Più che una risposta sembra proprio un tutorial, mi hai dato in una sola risposta una caterva di preziosissime informazioni (molte delle quali a me sconosciute).
Ti ringrazio mille per la risposta, veramente completa. Inoltre (senza farmi solo sorprendere dall'esposizione) la soluzione proprosta mi piace molto, sia perchè si avvicina di gran lunga al tipo di programmazione a me congeniale, sia per la chiara esposizione dei punti di forza di questa soluzione.
Ti ringrazio anche per non esserti limitato alla sola esposizione della soluzione, ma anche di aver confutato l'utilizzo delle variabili globali motivatamente.


Che dire,
proverò subito il sistema da te spiegato.

Mille grazie ancora,
e buona serata.

Ps: rispondi spesso ai miei quesiti risposte come questa mi sono preziosissime (come del resto qualunque risposta - attualmente -).

Ciao!
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2009, 15:19   #7
Krywen
Member
 
L'Avatar di Krywen
 
Iscritto dal: Sep 2006
Messaggi: 33
Aggiungo una cosa in cui mi sono scontrato in uno dei miei primi progetti:
nel caso in cui i campi della struttura siano tanti.
I casi sono due: continuare a passare l'indirizzo della struttura stessa a tutte le funzioni che usino informazioni contenute in essa, oppure.. passare ad ogni funzione solo i campi di tale struttura che le servono.
Pro e contro?

Se passi l'indirizzo della struttura:

- Esponi a libero accesso a tutti i campi della struttura a tutte le funzioni, quindi esse potrebbero accedere a parametri non di loro competenza. In progetti di piccole dimensioni non si nota molto il problema, ma se i campi sono tanti, si possono creare problemi di "competenze".

- è immediatamente più facile scrivere la funzione,(usa i campi che vuoi), ma non è chiaro come agisce la funzione: cioè idealmente i parametri di ingresso di una funzione sono i dati che riceve in input una funzione per perseguire il suo scopo. Così facendo rompi l'astrazione, gli passi una struttura che contiene tutto, e per capire cosa usa la funzione devi andar in giro per le righe a vedere a quali campi accede. Dunque può essere più complicato capire velocemente come lavora la funzione.

- può esserci un effetto indesiderato: una funzione che usa solo un campo A, può richiamare una funzione che usa un campo B delal struttura. In questo caso si può erroneamente pensare che la priam funzione usi solo il campo A, invece deve avere accesso anche al campo B per potre invocare la seconda funzione (è un altro esempio di come fraintendere l'input delle funzioni)

- il caso precedente può anche scaturire in una seria di chiamate a funzione non logiche: ad esempio una funzione che deve inizializzare i campi A e B, potrebbe chiamarne una altra per determinare il una media algoritmica su altre cose (il problema cioè è che ha poco senso vedere una funzione inizializza(struct *a) che richiama una funzione media(struct *a) solo perchè può farlo avendo visibilità a tutta la struttura).

- è difficile capire cosa fanno le funzioni se tutte hanno lo stesso parametro di ingresso (se ben documentato, con nomi esplicativi, può essere anche semplice, dipende come lavori).

Se passi alle funzioni i puntatori ai singoli campi della struttura:
- è un pò meno efficiente, ma puoi usarlo comunque se non è questo il tuo collo di bottiglia
- ogni funzione è astratta bene, cioè prende in ingresso solo i dati che le servono. Questo conferisce a tutto il programma una buona e dettagliata interfaccia tra le funzioni, nonchè un astrazione consistente.
- per quello detto sopra è più facile revisionare il programma e farlo capire agli altri esseri umani.

Appena mi verranno in mente altre motivazioni le scriverò.

Scegliere l'uno o l'altro metodo è una decisione da ponderare nel caso specifico, io non sò darti una risposta definitiva, ma usare un approccio misto mi sembra la soluzione peggiore.

P.S. Se ho sbagliato qlc di enorme o del codice è perché vengo dal C++ e non dal C.
__________________
Acer 5920 ''Gemstone'' 302
AMD Athlon XP 2400+ 2000Mhz|K7Upgrade-880|512 DDR|NVIDIA Ge-Force 6600 256 Mb| PX-W124TS SCSI
Krywen è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2009, 15:49   #8
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Non ricordo molto del C, ma potrebbe essere il caso di spezzare la struttura in sotto-strutture in modo che essa memorizzi i putatori alle sottostrutture? Si avrebbe una nelle parti da passare alle diverse funzioni che operano sulla struttura o una sua sottoparte.
Alla fine sembra una questione di design della struttura dati (e relative funzioni che ci operano sopra).
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2009, 17:20   #9
Krywen
Member
 
L'Avatar di Krywen
 
Iscritto dal: Sep 2006
Messaggi: 33
Si giusto, si possono scomporre i campi in 'sottosezioni', cioè in struct separate, e poi passare quelle. Non è una brutta idea. Bisogna prestare attenzione poi alle tante strutture diverse che si creano.

A lezione all'università mi sembra che varie parti del kernel sono sviluppate in questo modo.

Cmq anche questa è un opzione da valutare nel contesto specifico, ma grazie per avermela ricordata; devo tenermela in mente.
__________________
Acer 5920 ''Gemstone'' 302
AMD Athlon XP 2400+ 2000Mhz|K7Upgrade-880|512 DDR|NVIDIA Ge-Force 6600 256 Mb| PX-W124TS SCSI
Krywen è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2009, 17:34   #10
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Eh-eh, divide et impera!
Salvo poi non dover fare la stessa fine dell'impero romano...
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 01-09-2009, 20:31   #11
Y3PP4
Member
 
Iscritto dal: Jul 2009
Messaggi: 210
Quote:
Originariamente inviato da Krywen Guarda i messaggi
Aggiungo una cosa in cui mi sono scontrato in uno dei miei primi progetti:
nel caso in cui i campi della struttura siano tanti.
I casi sono due: continuare a passare l'indirizzo della struttura stessa a tutte le funzioni che usino informazioni contenute in essa, oppure.. passare ad ogni funzione solo i campi di tale struttura che le servono.
Pro e contro?

Se passi l'indirizzo della struttura:

- Esponi a libero accesso a tutti i campi della struttura a tutte le funzioni, quindi esse potrebbero accedere a parametri non di loro competenza. In progetti di piccole dimensioni non si nota molto il problema, ma se i campi sono tanti, si possono creare problemi di "competenze".

- è immediatamente più facile scrivere la funzione,(usa i campi che vuoi), ma non è chiaro come agisce la funzione: cioè idealmente i parametri di ingresso di una funzione sono i dati che riceve in input una funzione per perseguire il suo scopo. Così facendo rompi l'astrazione, gli passi una struttura che contiene tutto, e per capire cosa usa la funzione devi andar in giro per le righe a vedere a quali campi accede. Dunque può essere più complicato capire velocemente come lavora la funzione.

- può esserci un effetto indesiderato: una funzione che usa solo un campo A, può richiamare una funzione che usa un campo B delal struttura. In questo caso si può erroneamente pensare che la priam funzione usi solo il campo A, invece deve avere accesso anche al campo B per potre invocare la seconda funzione (è un altro esempio di come fraintendere l'input delle funzioni)

- il caso precedente può anche scaturire in una seria di chiamate a funzione non logiche: ad esempio una funzione che deve inizializzare i campi A e B, potrebbe chiamarne una altra per determinare il una media algoritmica su altre cose (il problema cioè è che ha poco senso vedere una funzione inizializza(struct *a) che richiama una funzione media(struct *a) solo perchè può farlo avendo visibilità a tutta la struttura).

- è difficile capire cosa fanno le funzioni se tutte hanno lo stesso parametro di ingresso (se ben documentato, con nomi esplicativi, può essere anche semplice, dipende come lavori).

Se passi alle funzioni i puntatori ai singoli campi della struttura:
- è un pò meno efficiente, ma puoi usarlo comunque se non è questo il tuo collo di bottiglia
- ogni funzione è astratta bene, cioè prende in ingresso solo i dati che le servono. Questo conferisce a tutto il programma una buona e dettagliata interfaccia tra le funzioni, nonchè un astrazione consistente.
- per quello detto sopra è più facile revisionare il programma e farlo capire agli altri esseri umani.

Appena mi verranno in mente altre motivazioni le scriverò.

Scegliere l'uno o l'altro metodo è una decisione da ponderare nel caso specifico, io non sò darti una risposta definitiva, ma usare un approccio misto mi sembra la soluzione peggiore.

P.S. Se ho sbagliato qlc di enorme o del codice è perché vengo dal C++ e non dal C.
Grazie mille per la chiara esposizione dei pro/contro di ogni soluzione.
In effetti, ammetto di non aver pensato a questa soluzione. Potrebbe essere utile, ma ogni passaggio di un campo della struct comporta, per l'appunto, la copia del valore, mentre passare il puntatore della intera struct evito questa situazione (almeno se non mi sfugge niente, l'unico modo di fare quello è di dereferenziare il puntatore alla struct, ottenendo e quindi passando il valore con il proprio tipo).
Sicuramente in molti casi potrà non importare ma dato che mi venne in mente questa domanda quando riflettevo a come realizzare un modo per contenere i dati ricavati dalla configurazione all'avvio dell'applicazione e renderli, in seguito, disponibili alle varie funzioni in tutto il programma, in un progetto grande potrebbe essere pesantuccio. Ma come già detto, bisogna studiare il caso. Il fatto di vedere, comunque, la cosa come una sorta di "database" a cui ogni funzione possa accedere agli specifici campi (dando l'effetto di definire dei privilegi) è una cosa che mi stuzzica molto
Quote:
Originariamente inviato da banryu79
Non ricordo molto del C, ma potrebbe essere il caso di spezzare la struttura in sotto-strutture in modo che essa memorizzi i putatori alle sottostrutture? Si avrebbe una nelle parti da passare alle diverse funzioni che operano sulla struttura o una sua sottoparte.
Alla fine sembra una questione di design della struttura dati (e relative funzioni che ci operano sopra)
Uhm. Questa sembra la soluzione idealmente posta tra le due (passaggio di puntatori e accesso ai soli valori necessari). Mi piace, devo tenerla in considerazione per una futura applicazione.


Grazie ad entrambi per la risposta entrambe molto utili (e apprezzate).
PS. Grazie Krywen per aver riscovato questo topic
__________________
La disumanità del computer sta nel fatto che, una volta programmato e messo in funzione, si comporta in maniera perfettamente onesta.
Isaac Asimov
Y3PP4 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Dark Perk Ergo e Sym provati tra wireless, software via browser e peso ridotto Dark Perk Ergo e Sym provati tra wireless, softw...
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 ...
Problema per il secondo stadio di un raz...
OnlyFans cambia proprietà? Avviat...
OnePlus estende il supporto alla ricaric...
Non solo Fold: Apple sta valutando la re...
TSMC deve raddoppiare la sua capacit&agr...
Raspberry Pi ritocca ancora i prezzi: la...
Missione Artemis II: lancio rinviato a m...
SpaceX acquisisce xAI: integrazione tra ...
Portatili Dell in forte sconto: Intel Co...
Intel Xeon 600, le nuove CPU per le work...
Tesla, è ufficiale: i Robotaxi fa...
DeepL sempre più evoluto: arriva ...
Un vecchio assegno venduto a 4.800 volte...
Amazfit punta ancora più in alto:...
Deep tech e venture capital: ScaleUp Lab...
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: 09:33.


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