[C] Strutture e puntatori

bad.alex
Ciao ragazzi. Avrei bisogno del vostro aiuto.
Sto lavorando sulle strutture e sui puntatori all'interno di questo codice (vi riporto la parte in cui ho problemi):

#include <stdio.h>
#include <stdlib.h>

struct prova
{
    /*variables */
    float *p;
} pro;

void inizio (struct prova);
void stampa (struct prova);

int main(){

inizio(pro);
stampa(pro);
return 0;
}

void inizio (struct prova pro){

int t;
pro.p=(float*)malloc(5 * sizeof(float));

t=0;

pro.p[0]=2;

}

void stampa (struct prova pro){

int i,t;

for(i=0; i<5; i++){

pro.p[t+1]=pro.p[t]; // Linea corrispondente all'errore. Prima di utilizzare le strutture, mi restituiva il valore 2.
printf("Stampo: %d -> %f\n", i, pro.p[t+1]);
}

}



Mi dà il seguente exc_bad_access(code=1, address=0xffffffff 5bdd89e0).
Non so se sia corretto procedere nel seguente modo. Considerate che sto familiarizzando soltanto da poco con le strutture e questo codice ne è, per l'appunto, la prova.
Inoltre volevo chiedervi se sia corretto allocare dinamicamente p all'interno della prima funzione (inizio) o se si debba fare nel main e/o nell'altra funzione (stampa).
Ciò che vorrei fare è tenere in memoria i valori e copiarli all'interno di un file di testo.
Spero possiate aiutarmi a capire dove sbaglio.

Vi ringrazio.

Alex

Risposte
Raptorista1
Perché in [inline]inizio[/inline] allochi 5 interi per un puntatore a [inline]float[/inline]?

bad.alex
Grazie per aver risposto, Raptorista. Hai ragione!
Non ho tenuto conto che per allocare la memoria in quel caso al posto di int dovevo sostituire float :oops:


EDIT: sostituendo

pro.p=(float*)malloc(5 * sizeof(float)); 


mi compare comunque lo stesso errore...

Raptorista1
Nel ciclo stai usando la variabile [inline]t[/inline] come indice in [inline]pro.p[t+1]=pro.p[t][/inline] anziché [inline]i[/inline].

bad.alex
Hai perfettamente ragione. Ad ogni modo, in quel modo doveva restituirmi in stampa i valori da 1 a 5 con p[t+1]=2, se non sbaglio.
Ho provato però ad eseguirlo senza ciclo for ma l'errore continua ad essere presente. E' possibile che stia sbagliando qualcosa nell'allocazione dinamica o nell'utilizzo delle variabili puntatore all'interno delle due funzioni?
In teoria, ciò che dovrebbe restituirmi dovrebbe essere il valore 2, come fissato nella funzione inizio... Non riesco proprio a capire come mai non riesca a visualizzare in stampa questo valore :(


EDIT: Allocando dinamicamente la memoria per p all'interno della funzione stampa non compare più il problema, malgrado si perda l'informazione contenuta all'interno della funzione inizio. Infatti mi stampa il valore 0.
C'è un modo per allocare dinamicamente questo puntatore senza che venga persa l'informazione contenuta all'interno delle altre funzioni? Inizialmente p[5] era una variabile globale...

Potreste inoltre dirmi come rendere equivalenti i seguenti codici? Vi ringrazio sin da ora!

#include <stdio.h>
#include <stdlib.h>

struct prova
{
    /*variables */
    float *p;
} pro;

void inizio (struct prova);
void stampa (struct prova);

int main(){

inizio(pro);
stampa(pro);
return 0;
}

void inizio (struct prova pro){

int t;
pro.p=(float*)malloc(5 * sizeof(float));

t=0;

pro.p[0]=2;

}

void stampa (struct prova pro){

int t;

pro.p[t+1]=pro.p[t]; // Cosa restituisce? 
printf("Stampo:  %f\n", pro.p[t+1]);


}



e

#include <stdio.h>
#include <stdlib.h>

float p[5];


void inizio ();
void stampa ();

int main(){

inizio();
stampa();
return 0;
}

void inizio (void){

int t;

t=0;

p[0]=2;

}

void stampa (void){

int t;

p[t+1]=p[t]; // Cosa dovrebbe restituire? 
printf("Stampo: %f\n", p[t+1]);

}


Raptorista1
Non mi stai seguendo! È sbagliato quando fai
int t;

pro.p[t+1]=pro.p[t];

perché [inline]t[/inline] non è stato inizializzato. Non ha un valore, quindi non puoi accedere all'elemento t-esimo. Quello che succede nella pratica è che [inline]t[/inline] contiene un valore casuale, e quando il programma va a leggere in quella posizione legge spazzatura. Se assegnassi [inline]t=0[/inline] tra le due istruzioni, funzionerebbe.

bad.alex
Grazie mille, Rapsodista. Io ho modificato (sperando di aver compreso quello che mi stai suggerendo, anche se capito in ritardo :) nel seguente modo:

#include <stdio.h>
#include <stdlib.h>

struct prova
{
    /*variables */
    float *p;
} pro;

void inizio (struct prova);
void stampa (struct prova);

int main(){

inizio(pro);
stampa(pro);
return 0;
}

void inizio (struct prova pro){

int t;
pro.p=(float*)malloc(5 * sizeof(float));

t=0;

pro.p[0]=2;

}

void stampa (struct prova pro){

int t;
t=0;
pro.p[t+1]=pro.p[t]; // Cosa restituisce? 
printf("Stampo:  %f\n", pro.p[t+1]);


}




Però, anche in questo caso, mi dà errore alla linea pro.p[t+1]=pro.p[t].
Se, invece delle strutture e dei puntatori, utilizzo variabili globali e array, l'errore scompare, sebbene mi stampi come valore 0 e non 2 come mi aspetterei.
E' anche vero, però, che ciò che vorrei provare a fare è: 1) scrivere una funzione che, all'interno di un ciclo for, inizializzi alcune variabili, tra cui p[t]; 2) svolgere delle operazioni attraverso un'altra funzione, che in questo caso è la funzione stampa(), in cui utilizzo quelle variabili.
La mia perplessità è anche legata all'utilizzo della funzione malloc(): è corretto quello che sto al momento facendo? Basta allocare dinamicamente lo spazio in memoria all'interno della funzione inizio() anche se le variabili sono utilizzate nella funzione stampa(), entrambe poi richiamate nel main? Il codice iniziale era il secondo, quello con gli array statici, poi trasformati in puntatori per provare a comprendere meglio questi argomenti.
Ti ringrazio, ad ogni modo, per tutto il tempo e l'aiuto che mi stai fornendo e ti chiedo scusa se ogni tanto sono lento a comprendere e a seguire i consigli e i suggerimenti: ho tante domande e curiosità riguardo a questi argomenti e vorrei capirli completamente :wink: Grazie ancora

vict85
L'errore è nel fatto che passi la struttura per valore invece che per riferimento. Insomma pro viene "mascherata" dalle variabili locali pro e non viene modificata in nessun modo. Comunque tutto continua ad essere globale.

bad.alex
Ti ringrazio vic85.
Potresti spiegarmi meglio come posso risolvere questo problema?
E' quantomeno corretta la parte dell'allocazione?
Per quanto riguarda il valore: dovrei in questo riscrivere pro.p[0]=2.; nella funzione stampa o c'e' un modo per riprendere questo valore? Sono un neofita, perdonatemi le domande ripetute e probabilmente anche banali. Vi ringrazio

vict85
Considerando che allochi una quantità fissa di elementi, puoi anche evitare di allocare memoria dinamicamente.

#include <stdio.h>
#include <stdlib.h>

struct prova {
	float p[5];
};

void inizio(struct prova * pr);
void stampa(struct prova const * pr);

int main() {
	struct prova pro;
	inizio(&pro);
	stampa(&pro);
	return 0;
}

void inizio(struct prova * pro) {
if( pro )
{
	*pro = (struct prova){ { 2 } };
}
}

void stampa(struct prova const * pro) {
	for( int t = 0; t != 5; ++t )
	{
		printf("prova[%d] = %g\n", t, pro->p[t]);
	}
}

bad.alex
Ti ringrazio vic85!
Effettivamente allocare dinamicamente qualcosa che contiene un numero fissato di elementi non ha senso.
Posso chiederti in quali casi e' conveniente utilizzare l'allocazione dinamica?

vict85
È una domanda complessa. In generale ogni volta che non sai la dimensione in anticipo o che devi allocare molta memoria. Comunque avresti potuto anche allocare direttamente l'intera struttura.

bad.alex
Grazie mille, vict85! Proverò ad allocare l'intera struttura, giusto per capire come si fa ;)
Grazie ancora per l'aiuto.

EDIT:
E' corretto procedere in questo modo?

struct book
{
    int b[100];
}*book1;

void print(struct book *);

int main(){
    
    book1=(struct book *)malloc(sizeof(book1));
    print(&book1);
}

void print(struct book *book1){

    int i;
    
    srand(time(NULL));
    
    for(i=0;i<100;i++){
        
        book1->b[i]=rand()%10;
        printf("Libro b[%d] %d\n", i, book1->b[i]);
    }

}

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.