Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi
Wind Tre 'accende' il 5G Standalone in Italia: si apre una nuova era basata sui servizi
Con la prima rete 5G Standalone attiva in Italia, WINDTRE compie un passo decisivo verso un modello di connettività intelligente che abilita scenari avanzati per imprese e pubbliche amministrazioni, trasformando la rete da infrastruttura a piattaforma per servizi a valore aggiunto
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh
OPPO Find X9 Pro: il camera phone con teleobiettivo da 200MP e batteria da 7500 mAh
OPPO Find X9 Pro punta a diventare uno dei riferimenti assoluti nel segmento dei camera phone di fascia alta. Con un teleobiettivo Hasselblad da 200 MP, una batteria al silicio-carbonio da 7500 mAh e un display da 6,78 pollici con cornici ultra ridotte, il nuovo flagship non teme confronti con la concorrenza, e non solo nel comparto fotografico mobile. La dotazione tecnica include il processore MediaTek Dimensity 9500, certificazione IP69 e un sistema di ricarica rapida a 80W
DJI Romo, il robot aspirapolvere tutto trasparente
DJI Romo, il robot aspirapolvere tutto trasparente
Anche DJI entra nel panorama delle aziende che propongono una soluzione per la pulizia di casa, facendo leva sulla propria esperienza legata alla mappatura degli ambienti e all'evitamento di ostacoli maturata nel mondo dei droni. Romo è un robot preciso ed efficace, dal design decisamente originale e unico ma che richiede per questo un costo d'acquisto molto elevato
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


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...
DJI Romo, il robot aspirapolvere tutto trasparente DJI Romo, il robot aspirapolvere tutto trasparen...
DJI Osmo Nano: la piccola fotocamera alla prova sul campo DJI Osmo Nano: la piccola fotocamera alla prova ...
FUJIFILM X-T30 III, la nuova mirrorless compatta FUJIFILM X-T30 III, la nuova mirrorless compatta
Il Galaxy S26 Edge potrebbe essere ancor...
Google riaccenderà una centrale n...
Crollo per Pornhub nel Regno Unito:-77% ...
La Germania accende il suo cannone laser...
Il meglio di Amazon in 2 minuti: tira ar...
ECOVACS risponde a Eureka e dimezza il p...
Durissimo colpo per Nintendo: l'ufficio ...
Scope elettriche al minimo storico su Am...
Blue Jay e Project Eluna: robotica e AI ...
Scede a 949€ il Samsung Galaxy S25 Ultra...
Blue Yeti Nano in super offerta su Amazo...
Netflix sta preparando un'offerta per Wa...
Prezzo impossibile, è sceso ancor...
Torna il migliore dei mini PC economici:...
USA, via libera all'uso di plutonio mili...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

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

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


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


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