Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica
DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica
Il nuovo gimbal mobile DJI evolve il concetto di tracciamento automatico con tre modalità diverse, un modulo multifunzionale con illuminazione integrata e controlli gestuali avanzati. Nel gimbal è anche presente un'asta telescopica da 215 mm con treppiede integrato, per un prodotto completo per content creator di ogni livello
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce
Abbiamo provato il nuovo HUAWEI Pura 80 Pro. Parliamo di uno smartphone che è un vero capolavoro di fotografia mobile, grazie ad un comparto completo in tutto e per tutto, In questa colorazione ci è piaciuto molto, ma i limiti hardware e software, seppur in netto miglioramento, ci sono ancora. Ma HUAWEI ha fatto davvero passi da gigante per questa nuova serie Pura 80. Buona anche l'autonomia e soprattutto la ricarica rapida sia cablata che wireless, velocissima.
Opera Neon: il browser AI agentico di nuova generazione
Opera Neon: il browser AI agentico di nuova generazione
Abbiamo provato il nuovo web browser con intelligenza artificiale della serie Opera accessibile tramite abbonamento. Ecco le nostre prime impressioni sulle funzionalità di Opera Neon basate su AI e come funzionano
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 30-08-2007, 13:47   #1
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
[C] Consigli su creazione lista

Devo creare una lista da una serie di dati statistici prelevati da un secondo programma che sono riuscito a completare.
La mia funzione che crea la lista riceve in ingresso: un risultato (stringa dim variabile da 1 a 30 char) e un id sessione (intero a 3 cifre).
Per ogni risultato voglio tenere conto di quante volte viene ricevuto in ogni sessione (sempre intero a 3 cifre) quindi ho scelto di fare una cosa del genere:

Codice:

typedef struct nodo
{
  struct nodo *next;
  char *result;
  int (*sessioni)[2];
}
Come posso sviluppare la funzione che riceve i dati non sapendo quanti siano in partenza? In particolare non so come comportarmi per inizializzare la lista (solo alla prima chiamata suppongo) e allocare lo spazio tramite malloc...
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °

Ultima modifica di Andrea16v : 03-09-2007 alle 11:39.
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 30-08-2007, 14:06   #2
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Come posso sviluppare la funzione che riceve i dati non sapendo quanti siano in partenza? In particolare non so come comportarmi per inizializzare la lista (solo alla prima chiamata suppongo) e allocare lo spazio tramite malloc...
Vedi un mio esempio in <questo> thread.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 30-08-2007, 21:56   #3
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Le operazioni da fare le ho capite (in altri linguaggi non avrei problemi a farlo), però non mi sono chiare proprio alcune operazioni che fai nella funzione append.
Lo riquoto un secondo:
Codice:
#include <stdio.h>
#include <stdlib.h>

typedef struct nodo
{
    int data;
    struct nodo *next;
} NODO, *PNODO, **PPNODO;

int List_Append (PPNODO pproot, int data)
{
    PNODO pnodo;

    if (pproot == NULL)
        return 0;

    if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
        return 0;

    pnodo->data = data;
    pnodo->next = NULL;

    while (*pproot != NULL)
        pproot = &(*pproot)->next;
    
    *pproot = pnodo;
    return 1;
}

int main (void)
{
    PNODO proot = NULL;

    List_Append (&proot, 27);
    List_Append (&proot, 7);
    List_Append (&proot, 87);

    return 0;
}
Ora, correggimi se sbaglio: con il primo if testi che la lista sia stata inizializzata, in caso contrario non è possibile utilizzarla quindi esci (con 0 perchè restituisci il numero di elementi inseriti).
Con il secondo if controlli che ci sia spazio sufficiente (la malloc non restituisca NULL), in caso contrario esci. La mia malloc è molto più complessa avendo un array di lunghezza non fissa?
Poi assegni i valori al nuovo nodo (con puntatore next nullo in quanto lo metti in fondo), scorri "ricorsivamente" la struttura sino alla fine e inserisci...


grazie mille!
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2007, 10:13   #4
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
però non mi sono chiare proprio alcune operazioni che fai nella funzione append.
Non c'è problema, spiego subito.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Ora, correggimi se sbaglio: con il primo if testi che la lista sia stata inizializzata, in caso contrario non è possibile utilizzarla quindi esci
Il primo test controlla 'pproot' che è un puntatore ad una variabile di tipo PNODO. In quel punto della funzione non interessa tanto se il PNODO è NULL (che vuol dire lista vuota) ma che l'indirizzo passato di tale variabile sia NULL o no. È chiaro che se passi un indirizzo con una espressione &proot, l'indirizzo non è certamente NULL ma tecnicamente la possibilità di passare un NULL alla Append esiste.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
(con 0 perchè restituisci il numero di elementi inseriti).
No, per come l'ho pensata io è da intendere: 0=append fallito, 1=append riuscito. In pratica è uno stato booleano.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Con il secondo if controlli che ci sia spazio sufficiente (la malloc non restituisca NULL), in caso contrario esci.
Esatto, questa è una cosa molto importante.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
La mia malloc è molto più complessa avendo un array di lunghezza non fissa?
No, non dovrebbe essere molto più complessa, bisogna solo vedere come è fatta la tua struttura dati.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Poi assegni i valori al nuovo nodo (con puntatore next nullo in quanto lo metti in fondo), scorri "ricorsivamente" la struttura sino alla fine e inserisci...
Sì, tra l'altro ho usato il "trucchetto" di usare un puntatore a puntatore, perché in questo modo non devo differenziare tra primo nodo (da assegnare al root) o successivi nodi (da assegnare al next precedente).
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2007, 16:58   #5
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Penso di aver capito abbastanza: ho provato ad adattarlo ai miei scopi, per ora lasciando ancora da parte le cose difficili, questo è il risultato (che definirei abbastanza penoso..):
Codice:
typedef struct nodo
{
    char *result;
    int sessione;
    struct nodo *next;
} NODO, *PNODO, **PPNODO;



int main() {

  PNODO proot = NULL;
    
  list_Append (&proot, "PrimoRisultato", 1);
  list_Append (&proot, "SecondoRisultato", 2);
  list_Append (&proot, "TerzoRisultato", 2);
  list_Append (&proot, "QuartoRisultato", 3);
  
  stampa (&proot);

  return 0;
}







int list_Append (PPNODO pproot, char *result, int sessione)
{
    PNODO pnodo;

    if (pproot == NULL)
        return 0;

    if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
        return 0;

    pnodo->result = result;
    pnodo->sessione = sessione;	
    pnodo->next = NULL;

    while (*pproot != NULL)
	pproot = &(*pproot)->next;
       
    *pproot = pnodo;
    return 1;
}



void stampa (PPNODO pproot)
{	
	if (pproot == NULL)
		exit(1);

	printf("Risultato: %s\n", (*pproot)->result);
	printf("Id sessione: %d\n\n", (*pproot)->sessione);
	stampa((*pproot)->next);
}
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 31-08-2007, 17:10   #6
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Codice:
void stampa (PPNODO pproot)
{	
	if (pproot == NULL)
		exit(1);

	printf("Risultato: %s\n", (*pproot)->result);
	printf("Id sessione: %d\n\n", (*pproot)->sessione);
	stampa((*pproot)->next);
}
Io farei stampa così:

Codice:
void stampa (PNODO pnodo)
{
    while (pnodo != NULL)
    {
        printf("Risultato: %s\n", pnodo->result);
        printf("Id sessione: %d\n\n", pnodo->sessione);
        pnodo = pnodo->next;
    }
}
Per il resto mi sembra ok. Una cosa sola a cui prestare attenzione sono gli eventuali puntatori che rappresentano dei dati nella struttura del nodo (cioè escluso il next). Nel tuo caso è il puntatore 'result'. Copi semplicemente il valore del puntatore ma questo vuol dire che non è la lista ad essere "responsabile" e "proprietaria" dell'area di memoria a cui punta ma è il chiamante all'esterno che deve gestirla.
Finché assegni l'indirizzo di stringhe "literal", no problem.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 11:49   #7
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Ho provato a complicare un po' le cose aggiungendo la matrice.
Ad ogni risultato ho associato una matrice di due colonne in cui la prima riporta il numero di sessione e la seconda il numero di volte che il risultato è pervenuto in quella sessione. Dovrei trovare un modo per scorrere la matrice verticalmente sino all'ultima riga, ma ora come ora non mi sono venute idee (salvo inserire nella struct un campo che mi dice il numero di sessioni in cui appare quel risultato). Inoltre c'è sicuramente anche qualche problema di allocazione...

Codice:
int list_Append (PPNODO pproot, char *result, int sessione)
{
    PNODO pnodo;
    int i;

    if (pproot == NULL)
        return 0;

    if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
        return 0;

    while (*pproot != NULL) {
	/*cerco il risultato nella lista dei risultati*/
	if((*pproot)->result) == result) {
                /*cerco la sessione all'interno del nodo*/ 
		for(i=0;i<???) /*dovrei iterare sino all'ultima riga*/
			if( (*pproot)->sessioni[i][0] == sessione){
				(*pproot)->sessioni[i][1]++;
				return 1;
			}
		}
 		/*la sessione non e' presente, la aggiungo*/
		(*pproot)->sessioni[i][0] = sessione;
		(*pproot)->sessioni[i][1] = 1;
		return 1;
	}	
	pproot = &(*pproot)->next;
    }
  
  /* il risultato non e' presente, lo aggiungo in coda*/
  pnodo->result = result;
  pnodo->sessioni[0][0] = sessione;	
  pnodo->sessioni[0][1] = 1;	
  pnodo->next = NULL;

  *pproot = pnodo;
  return 1;
}
ps: il modello della struct è nel primo post!
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 13:13   #8
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Ho provato a complicare un po' le cose aggiungendo la matrice.
Puoi spiegare meglio come deve essere questa matrice?

Perché tra l'altro:

a) Fare int (*sessioni)[2] vuol dire "un puntatore ad un array di 2 int". Ho il dubbio che probabilmente non è proprio quello che ti serve.

b) Nella funzione non assegni un valore a questo puntatore. Fai:
pnodo->sessioni[0][0] = sessione;
pnodo->sessioni[0][1] = 1;
e cioè cerchi di accedere agli elementi nell'array puntato ma pnodo->sessioni non è inizializzato, quindi ... boh.

c) Nel while fai dei return 1 ma in caso di tale uscita, hai comunque allocato un NODO che poi non viene usato (memory leak).
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)

Ultima modifica di andbin : 03-09-2007 alle 13:19.
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 14:23   #9
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Quote:
Originariamente inviato da andbin Guarda i messaggi

a) Fare int (*sessioni)[2] vuol dire "un puntatore ad un array di 2 int". Ho il dubbio che probabilmente non è proprio quello che ti serve.
La specifica che devo seguire riguardo alla struct parla in effetti di "puntatore ad un array di 2 int" ma, ragionando un po' sulla cosa, non ho trovato il modo di esprimere quello che mi serve in quel modo, quindi ho pensato di usare una matrice in cui memorizzo un id sessione nella prima colonna e il numero di hit di quel risultato in quella sessione nella seconda colonna. La matrice avrà un numero di righe che puo' crescere nel tempo: viene inizializzata ad 1 all'atto della creazione del nodo con l'arrivo del primo risultato e può arrivare a 999.
E' valida come idea oppure effettivamente si poteva fare anche con un puntatore ad un array di 2 int?
Quote:
b) Nella funzione non assegni un valore a questo puntatore. Fai:
pnodo->sessioni[0][0] = sessione;
pnodo->sessioni[0][1] = 1;
e cioè cerchi di accedere agli elementi nell'array puntato ma pnodo->sessioni non è inizializzato, quindi ... boh.
Il mio intento era di creare un nuovo nodo da aggiungere alla lista e assegnare alle variabili della struct i valori ricevuti dalla funzione come parametro.
La dinamica del tutto è la seguente: ricevo un risultato, controllo se il risultato è già in lista, se non è in lista lo aggiungo in coda, se è già in lista controllo se era già stato ricevuto in quella sessione scorrendo la prima colonna della matrice, in caso positivo aumento il numero di hit di quella sessione e esco, in caso negativo aggiungo una riga alla matrice con il numero sessione e 1 come numero hit.

Quote:
c) Nel while fai dei return 1 ma in caso di tale uscita, hai comunque allocato un NODO che poi non viene usato (memory leak).
Giusto, questo è un errore che non avevo visto. Chiamerò la malloc del NODO solo quando sono arrivato al caso in cui debba crearlo da zero. Ma ogni volta che aggiungo una riga alla matrice devo allocare esplicitamente il relativo spazio o viene fatto "in automatico"? Viva Java...
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 14:39   #10
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
La specifica che devo seguire riguardo alla struct parla in effetti di "puntatore ad un array di 2 int" ma, ragionando un po' sulla cosa, non ho trovato il modo di esprimere quello che mi serve in quel modo, quindi ho pensato di usare una matrice in cui memorizzo un id sessione nella prima colonna e il numero di hit di quel risultato in quella sessione nella seconda colonna. La matrice avrà un numero di righe che puo' crescere nel tempo: viene inizializzata ad 1 all'atto della creazione del nodo con l'arrivo del primo risultato e può arrivare a 999.
E' valida come idea oppure effettivamente si poteva fare anche con un puntatore ad un array di 2 int?
Allora i due valori rappresentano un "record" e devi fare un array di record. Pertanto è meglio se definisci una struttura:
Codice:
typedef struct
{
    int id;
    int hit;
} SESSIONE;
e poi metti nel nodo un puntatore a SESSIONE:
Codice:
SESSIONE *sessioni;
L'array delle sessioni ovviamente lo allochi dinamicamente quando crei un nodo e lo assegni al puntatore.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)

Ultima modifica di andbin : 03-09-2007 alle 14:42.
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 16:15   #11
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Ho guardato un po' come verrebbe con l'array di record e cosa dovrei cambiare negli altri moduli del programma e mi viene un bel caos, dovrei rifare una marea di cose che al momento sono faticosamente funzionanti, preferisco insistere sulla strada della matrice.
Codice:
RisultatoA 
           [2][6]
           [4][3]
           [7][1]
da intendersi come: nella seconda sessione ricevuto sei volte, nella quarta sessione ricevuto tre volte, ecc

La dinamica del tutto è la seguente: ricevo un risultato, controllo se il risultato è già in lista, se non è in lista lo aggiungo in coda, se è già in lista controllo se era già stato ricevuto in quella sessione scorrendo la prima colonna della matrice, in caso positivo aumento il numero di hit di quella sessione e esco, in caso negativo aggiungo una riga alla matrice con il numero sessione e 1 come numero hit.
Qualche suggerimento su come gestire le malloc nei vari casi?
Questo è quando ho prodotto:

nsess è stato aggiunto alla struct: indica il numero di sessioni in cui il risultato è presente, e quindi il numero di righe della matrice...
Codice:
int list_Append (PPNODO pproot, char *result, int sessione)
{
    PNODO pnodo;
    int i;	
    
    if (pproot == NULL)
        return 0;

    while (*pproot != NULL) {
	
	if(((*pproot)->result) == result) {
		for(i=0;i<(*pproot)->nsess;i++){ 
			if( (*pproot)->sessioni[i][0] == sessione){
				(*pproot)->sessioni[i][1]++;
				return 1;
			}
		}
 		/*la sessione non e' presente, la aggiungo*/
		(*pproot)->sessioni[i][0] = sessione;
		(*pproot)->sessioni[i][1] = 1;
		(*pproot)->nsess++;
		return 1;
	}	
	pproot = &(*pproot)->next;
    }
  
  /* il risultato non e' presente, lo aggiungo in coda*/
  if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
        return 0;
  pnodo->result = result;
  pnodo->sessioni[0][0] = sessione;	
  pnodo->sessioni[0][1] = 1;	
  pnodo->next = NULL;
  pnodo->nsess = 1;

  *pproot = pnodo;
  return 1;
}
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °

Ultima modifica di Andrea16v : 03-09-2007 alle 16:50.
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 20:48   #12
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Codice:
  if ((pnodo = (PNODO) malloc (sizeof (NODO))) == NULL)
        return 0;
  pnodo->result = result;
  pnodo->sessioni[0][0] = sessione;	
  pnodo->sessioni[0][1] = 1;
Continuo a non vedere la allocazione di una area per questi benedetti int. A costo di essere petulante, ripeto che pnodo->sessioni è solo un puntatore e gli va assegnato qualcosa prima di poterlo dereferenziare (accedere al contenuto puntato).

Un esempio banale:
Codice:
int (*sessioni)[2];
int arr[2];

sessioni = &arr;
In questo caso assegno l'indirizzo di un altro array.

Ma posso pure allocare dinamicamente la memoria per i due int:
Codice:
int (*sessioni)[2];

sessioni = (int(*)[2]) malloc (2 * sizeof (int));
E se volessi allocare 10 righe:
Codice:
sessioni = (int(*)[2]) malloc (2 * 10 * sizeof (int));

sessioni[0][0] = ....
sessioni[0][1] = ....
....
sessioni[9][0] = ....
sessioni[9][1] = ....
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 03-09-2007, 21:33   #13
nico88desmo
Senior Member
 
Iscritto dal: Jul 2006
Messaggi: 1568
Mi intrometto nella discussione chiedendo 2 cose;

Questi due modi sono equivalenti vero?
Codice:
int (*sessioni)[2];
int arr[2];
come pure questi, giusto?
Codice:
&(*pproot);
pproot;

Ultima modifica di nico88desmo : 03-09-2007 alle 22:20.
nico88desmo è offline   Rispondi citando il messaggio o parte di esso
Old 04-09-2007, 09:28   #14
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da nico88desmo Guarda i messaggi
Questi due modi sono equivalenti vero?
Codice:
int (*sessioni)[2];
int arr[2];
No sono due cose diverse, il primo è "un puntatore ad un array di 2 int" mentre il secondo è "un array di due int". L'indirizzo del secondo è assegnabile al primo (come appunto nel mio esempio sopra).

Quote:
Originariamente inviato da nico88desmo Guarda i messaggi
come pure questi, giusto?
Codice:
&(*pproot);
pproot;
In questo caso sì, sono equivalenti (sebbene il primo sia un po' "stupido").
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 05-09-2007, 11:58   #15
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
...vedi post sotto!
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °

Ultima modifica di Andrea16v : 10-09-2007 alle 00:43.
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2007, 00:43   #16
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Quote:
Originariamente inviato da andbin Guarda i messaggi
Continuo a non vedere la allocazione di una area per questi benedetti int. A costo di essere petulante, ripeto che pnodo->sessioni è solo un puntatore e gli va assegnato qualcosa prima di poterlo dereferenziare (accedere al contenuto puntato).
Giusto, mi sono un po' guardato la malloc e la realloc, pensavo l'assegnamento dello spazio fosse del tutto automatico...
Comunque ancora un paio di cose non mi tornano:

la mia struttura è fatta così:

typedef struct nodo
{
struct nodo *next;
char *result;
int (*sessioni)[2];
int pippo; //aggiunto per esempio
int pluto[4]; //aggiunto per esempio
}

Quando chiamo la malloc con il parametro sizeof (NODO) quanto spazio viene allocato per la struttura sopra?
Esempio: se voglio scrivere qualcosa nel campo nodo->result potrei farlo senza richiamare la malloc (ho un esempio però che non funziona!), mentre se voglio scrivere in sessioni[..] non posso in quanto sessioni è un puntatore e la malloc precedente non ha allocato spazio per i puntatori definiti nella struct..
pluto[0] dovrebbe essere "disponibile" senza ulteriori malloc però se volessi espandere l'array a 6 posizioni potrei chiamare realloc(&pluto, 6*sizeof(int))
Vorrei insomma capire con che criterio viene allocato lo spazio con la chiamata sizeof(NODO)
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2007, 09:39   #17
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Quando chiamo la malloc con il parametro sizeof (NODO) quanto spazio viene allocato per la struttura sopra?
Ogni variabile ha una dimensione ben precisa, pure i puntatori, ovviamente.

Prendiamo la tua struttura originale:
Codice:
typedef struct nodo
{
  struct nodo *next;
  char *result;
  int (*sessioni)[2];
}
Sono tutti e tre dei puntatori. Su architetture a 32 bit un puntatore è appunto 32 bit, quindi 4 byte. Totale: 12 byte allocati per la struttura.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Esempio: se voglio scrivere qualcosa nel campo nodo->result potrei farlo senza richiamare la malloc (ho un esempio però che non funziona!)
La questione è un'altra: a 'result' potresti assegnare l'indirizzo di una stringa literal e non avresti mai problemi, potresti assegnare l'indirizzo di una stringa allocata al di fuori della funzione di Append oppure nella funzione Append potresti allocare memoria sufficiente e quindi duplicare la stringa passata.
La questione quindi è: chi deve gestire la memoria di quella stringa, in pratica chi deve essere "responsabile" della gestione dell'area di memoria puntata da result.

Se nella funzione di Append fai una cosa come:

pnodo->result = result;

vuol dire semplicemente che la funzione non sa nulla di come è stata gestita l'allocazione della stringa e si limita solo a copiare l'indirizzo. Quindi sei tu che dovrai preoccuparti all'esterno di allocare/deallocare (eventualmente) la memoria.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
mentre se voglio scrivere in sessioni[..] non posso in quanto sessioni è un puntatore e la malloc precedente non ha allocato spazio per i puntatori definiti nella struct..
La malloc per il NODO ha allocato spazio per i puntatori. Ma se tu che dovrai valorizzarli con opportuni valori.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
pluto[0] dovrebbe essere "disponibile" senza ulteriori malloc però se volessi espandere l'array a 6 posizioni potrei chiamare realloc(&pluto, 6*sizeof(int))
Per come hai dichiarato pluto, cioè int pluto[4];, non puoi ridimensionarlo in alcun modo. Quello è un array di dimensione fissa. Nella struttura ci saranno quindi già 4*sizeof(int) byte allocati per questa variabile. E l'indirizzo di questo array è anche fisso. Per dirla in altri termini, l'epressione 'pluto' non può essere un l-value, cioè non puoi fare ad esempio: pluto = realloc........
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2007, 11:04   #18
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Quote:
Originariamente inviato da andbin Guarda i messaggi
Ogni variabile ha una dimensione ben precisa, pure i puntatori, ovviamente.

Prendiamo la tua struttura originale:
Codice:
typedef struct nodo
{
  struct nodo *next;
  char *result;
  int (*sessioni)[2];
}
Sono tutti e tre dei puntatori. Su architetture a 32 bit un puntatore è appunto 32 bit, quindi 4 byte. Totale: 12 byte allocati per la struttura.
Ok, quindi nel momento in cui dichiaro un puntatore, ho sempre un'allocazione di 4 byte, indipendentemente dal "tipo" del puntatore, un puntatore ad un array di 2 int, come sopra, sarà uguale ad un puntatore ad un array di 20 int, con un campo solo per l'indirizzo iniziale dell'array! Per errore sono riuscito a scrivere int in questo campo senza che il compilatore mi avvisasse, quindi pensavo lo spazio per i 2 int fosse già allocato!
Quote:
La questione è un'altra: a 'result' potresti assegnare l'indirizzo di una stringa literal e non avresti mai problemi, potresti assegnare l'indirizzo di una stringa allocata al di fuori della funzione di Append oppure nella funzione Append potresti allocare memoria sufficiente e quindi duplicare la stringa passata.
Capisco ora a cosa ti riferivi in un post precedente. Nel mio caso la memoria deve essere gestita all'interno del nodo, e il programma che manda le stringhe ad append mi invia un array di caratteri, quindi dovrei allocare spazio e duplicare con strcpy o strncpy. Ho fatto delle prove anche inviando delle stringhe literal "ciao" e in effetti non serve nè allocare, nè duplicare...

Quote:
Per come hai dichiarato pluto, cioè int pluto[4];, non puoi ridimensionarlo in alcun modo. Quello è un array di dimensione fissa. Nella struttura ci saranno quindi già 4*sizeof(int) byte allocati per questa variabile. E l'indirizzo di questo array è anche fisso. Per dirla in altri termini, l'epressione 'pluto' non può essere un l-value, cioè non puoi fare ad esempio: pluto = realloc........
Giusto, perchè la realloc funziona solo su locazioni di mem. ottenute tramite malloc...
Nel caso avessi dichiarato quindi sessioni come array di 2 int e non puntatore a, non avrei potuto aumentarlo dinamicamente a seconda delle esigenze.
Ultima cosa: tutte le volte che chiamo la malloc() è necessario testarne il valore di ritorno? Nel mio caso ho 3 chiamate: una sul sizeof(NODO), la seconda per la stringa e la terza per la matrice/array, quindi mi ritroverei un codice un po' incasinato..
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2007, 11:27   #19
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Per errore sono riuscito a scrivere int in questo campo senza che il compilatore mi avvisasse, quindi pensavo lo spazio per i 2 int fosse già allocato!
Perché la malloc non azzera il blocco di memoria, in pratica ci trovi "spazzatura", quindi un indirizzo che potrebbe essere NULL o non NULL e in tal caso non sai a cosa punta. Se lo dereferenzi per scriverci, può succedere un po' di tutto, dal sporcare altre zone vitali del programma (e avere crash in seguito) al segmentation fault immediato.

Quote:
Originariamente inviato da Andrea16v Guarda i messaggi
Ultima cosa: tutte le volte che chiamo la malloc() è necessario testarne il valore di ritorno? Nel mio caso ho 3 chiamate: una sul sizeof(NODO), la seconda per la stringa e la terza per la matrice/array, quindi mi ritroverei un codice un po' incasinato..
Sì, sarebbe meglio se testassi il valore fornito da ogni malloc. Non è che ti si incasina più di tanto il codice.
Se ad esempio la malloc del NODO e ok ma poi la malloc per sessioni fallisce, beh, basta che fai il free di ciò che hai allocato prima e ritorni NULL.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 12-09-2007, 12:40   #20
Andrea16v
Senior Member
 
L'Avatar di Andrea16v
 
Iscritto dal: Mar 2003
Messaggi: 3852
Ho fatto ancora delle prove sulla realloc, il frammento seguente mi funziona, ma è giusto dal punto di visto logico? Se ho capito bene il programma potrebbe funzionare anche eliminando la chiamata alla malloc(), però lo spazio non verrebbe riservato, quindi ulteriori operazioni potrebbero andare ad alterare il contenuto dell'array...

Codice:
int (*s)[2];
int i=0, dim=2;

s = (int(*)[dim]) malloc (dim * sizeof(int));

while(i<dim){
	*(s[i])= ...;
	i++;
}

dim = dim + 2; // aggiungo due posizioni
s = (int(*)[dim]) realloc(s, dim * sizeof(int)); 
*(s[i]) = ...;
*(s[i+1]) = ...;

dim = dim + 6; // ne aggiungo altre sei
s = (int(*)[dim]) realloc(s, dim * sizeof(int)):
*(s[i+2]) = ...;
*(s[i+3]) = ...;
...
*(s[i+7]) = ...;
Qualcosa ancora non mi è chiaro: quando dichiaro un puntatore ad un array, a cosa serve dichiarare la lunghezza dell'array? X es: dichiarare (int*)s[2] è diverso da dichiarare (int*)s[10] o impatta solo sulla intelligibilità del comando?
Idem dicasi per il cast sulle chiamate malloc e realloc è solo una questione stilistica o impatta in qualche modo sulla "gestione dello spazio"?
__________________
Cerco fotocamera con buono zoom!! CLICCA!
° Moderatore del Forum Ufficiale di ElaborarE (responsabile sezione HI-FI e Car Audio) °
Andrea16v è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


DJI Osmo Mobile 8: lo stabilizzatore per smartphone con tracking multiplo e asta telescopica DJI Osmo Mobile 8: lo stabilizzatore per smartph...
Recensione Pura 80 Pro: HUAWEI torna a stupire con foto spettacolari e ricarica superveloce Recensione Pura 80 Pro: HUAWEI torna a stupire c...
Opera Neon: il browser AI agentico di nuova generazione Opera Neon: il browser AI agentico di nuova gene...
Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi Wind Tre 'accende' il 5G Standalone in Italia: s...
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh OPPO Find X9 Pro: il camera phone con teleobiett...
1.200 CV e drift a 213 km/h: la supercar...
Shenzhou-21: esperimenti sui topi in orb...
Cloudera punta su cloud privato e intell...
Il mistero del Ryzen 7 9700X3D: prezzo p...
Posticipato il rientro dell'equipaggio c...
Propaganda russa e hactivism fra le prin...
Superluna del Castoro: stasera il satell...
NVIDIA regala una GeForce RTX 5090 Found...
Snowflake punta su Intelligence, l'IA pe...
Volkswagen realizzerà i propri chip per ...
Formula E GEN4 svelata: 600 kW di potenz...
PC Desktop HP Victus con RTX 4060 e Ryze...
Fastnet, il 'mega-cavo' di AWS che pu&og...
Offerte Amazon da non perdere: GeForce R...
Clima, l'UE trova l'accordo sul taglio d...
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: 22:52.


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