Pagina 1 di 1

Puntatori e vettori.

Inviato: dom 12 lug 2009, 20:56
da Mercyful
Salve a tutti,
devo risolvere questo problema su un piccolo codice di un'esercizio che stavo facendo, ma non riesco a
capire perchè funziona solamente in certi casi. Vi sarei grato se mi dareste una mano a trovare l'errore!
Il codice è tutto quà:

Codice: Seleziona tutto

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

int plus(int, int);
int minus(int, int);
int (*choice(char))(int, int);
int execute_operation(int, int, int(*op)(int, int));

int main(int argc, char *argv[]) {

	int result = 0;
	int i = 0;
	int vect[2] = {3, 2};
	
	printf("The result is: %d\n", vect[(result = execute_operation(5, 2, choice('-')))]);
	printf("The result is: %d\n", vect[(result = execute_operation(4, 2, choice('-')))]);
	
	return EXIT_SUCCESS;
}

int plus(int a, int b) {
	return (a + b);
}

int minus(int a, int b) {
	return (a - b);
}

int (*choice(char c))(int, int) {
	switch (c) {
		case '+':
			return &plus;
		case '-':
			return &minus;
		default:
			return NULL;
	}
}

int execute_operation(int a, int b, int(*op)(int x, int y)) {
	return op((int)&a,(int)&b);
}
Non ci sono errori di compilazione, penso che sia colpa del pc a 64 bit anche se non ho l'OS a 64
Grazie in anticipo!!

Re: Puntatori e vettori.

Inviato: dom 12 lug 2009, 21:15
da robbybby
Dacci qualche dettaglio in piu':
in quali casi funziona?
in quali casi non funziona?
cosa fa quando non funziona?

Poi ti converrebbe testare il valore ritornato da choice(), prima di dereferenziarlo. Se ritorna NULL, come minimo il tuo programmino va in crash.

Re: Puntatori e vettori.

Inviato: dom 12 lug 2009, 21:26
da Mercyful
l'output è sempre 2 , il risultato di choice è giusto in quanto mi da l'indirizzo di minus (anche se non è semplice da testare).
Bhe funziona nel senso che dovrebbe dare 3 e 2 ma da sempre 2.

Re: Puntatori e vettori.

Inviato: dom 12 lug 2009, 21:30
da Luke88
non ho mai giocato con i puntatori a funzione, comunque....

vect[] ha 2 elementi....
vect[0] = 3, vect[1] = 2, ma vect[2] o vect[3] non ci sono, quindi quando tu fai:

Codice: Seleziona tutto

printf("The result is: %d\n", vect[(result = execute_operation(5, 2, choice('-')))]);
gli dici di cercare il 4° elemento (vect[3]), e lui ovviamente non lo trova.
a parte che "result" non è necessario, potresti benissimo fare

Codice: Seleziona tutto

printf("The result is: %d\n", vect[execute_operation(5, 2, choice('-'))]);
ma poi:

Codice: Seleziona tutto

int execute_operation(int a, int b, int(*op)(int x, int y)) {
   return op((int)&a,(int)&b);
}
...uh?
perchè gli passi il cast a int dell indirizzo della variabile??
dovrebbe bastare
return op(a, b);

P.S.:
se usi la shell per compilare spesso sono utili anche i "warning", non solo gli errori di compilazione...
usa "gcc -Wall sorgente.c"

Re: Puntatori e vettori.

Inviato: dom 12 lug 2009, 21:39
da m0rdr3d
Luke88 ha scritto:...uh?
perchè gli passi il cast a int dell indirizzo della variabile??
dovrebbe bastare
return op(a, b);
Il problema è proprio quello, tu le operazioni le esegui sugli indirizzi delle variabili, per cui ti vengono ritornati valori a caso (nel mio caso -4).
Rimuovi gli operatori & e il cast ad int e tutto funzionerà.

P.S.: ovviamente il processore non può influire in questo caso, è il sistema operativo che alloca la memoria, indipendentemente dal processore sottostante.

P.S.: può un po' chiarirti le idee (o forse confondertele) provare a eseguire in execute_operation la seguente riga:

Codice: Seleziona tutto

printf( "a= %i, b= %i, &a= %i, &b= %i\n", a, b, &a, &b );
che ti stampa i valori di a, di b e di &a e &b

Re: Puntatori e vettori.

Inviato: dom 12 lug 2009, 22:02
da Mercyful
@Luke88 si sembra ora con a e b funzioni, ma non è l'unico forse..., visto che funziona solo il primo.
il compilatore da shell lo uso sempre cosi... non mi da ne warning ne errori.

ora il risultato è 3 0 0 con questo codice:

Codice: Seleziona tutto

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

int plus(int, int);
int minus(int, int);
int (*choice(char))(int, int);
int execute_operation(int, int, int(*op)(int, int));

int main(int argc, char *argv[]) {

	int i = 0;
	int result = 0;
	int vect[2] = {3 , 2};
	
	
	printf("The result is: %d\n", vect[(result = execute_operation(5, 2, choice('-')))]);
	printf("The result is: %d\n", vect[(result = execute_operation(4, 2, choice('-')))]);
	printf("The result is: %d\n", i);
	
	return EXIT_SUCCESS;
}

int plus(int a, int b) {
	return (a + b);
}

int minus(int a, int b) {
	return (a - b);
}

int (*choice(char c))(int, int) {
	switch (c) {
		case '+':
			return &plus;
		case '-':
			return &minus;
		default:
			return NULL;
	}
}

int execute_operation(int a, int b, int(*op)(int x, int y)) {
	return op( a , b );
}


Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 10:00
da Luke88
Luke88 ha scritto: vect[] ha 2 elementi....
vect[0] = 3, vect[1] = 2, ma vect[2] o vect[3] non ci sono, quindi quando tu fai:

Codice: Seleziona tutto

printf("The result is: %d\n", vect[(result = execute_operation(5, 2, choice('-')))]);
gli dici di cercare il 4° elemento (vect[3]), e lui ovviamente non lo trova.
a parte che "result" non è necessario, potresti benissimo fare

Codice: Seleziona tutto

printf("The result is: %d\n", vect[execute_operation(5, 2, choice('-'))]);
:p
execute_operation(5, 2, choice('-')) ritorna l'intero 3, per cui tu vai a cercare vect[3].
hai dichiarato vect come vect[2]. ergo ci sono solo gli elementi vect[0] e vect[1].
devi dichiarare almeno vect[4] (e inserire gli elementi) se vuoi usare quell'array... oppure fai altre operazioni con execute_operation... a te la scelta...

anche se vai oltre la dimensione dell'array il compilatore non ti da errori perchè effettivamente non viene controllata la dimensione di vect[].
in pratica tu stai accedendo a memoria che potrebbe contenere un qualsiasi altro dato del programma stesso... se accedi troppo in la vai anche in segmentation fault, ovvero accedi a memoria a cui non potresti accedere, il sistema operativo se ne accorge e ti termina il programma... chiaro?

P.S.: consiglio il Kerninghan come buona lettura di programmazione C :p

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 10:37
da Mercyful
Ciao,
si Luke hai ragione, però quello che sto facendo è quello che voglio fare, mancava giusto un'altra correzione,
in effetti non ho detto come doveva comportarsi il programma, in pratica deve accedere a quelle locazioni di memoria, e il risultato deve essere giusto.
Ecco, così dovrebbe essere giusto.

Codice: Seleziona tutto

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

int plus(int, int);
int minus(int, int);
int (*choice(char))(int, int);
int execute_operation(int, int, int(*op)(int, int));

int main(int argc, char *argv[]) {

	int result = 0;
	int result1 = 0;
	int vect[2] = {3 , 2};
	
	
	printf("The result is: %d\n", vect[(result1 = execute_operation(5, 2, choice('-')))]);
	printf("The result is: %d\n", vect[(result = execute_operation(4, 2, choice('-')))]);
	
	return EXIT_SUCCESS;
}

int plus(int a, int b) {
	return (a + b);
}

int minus(int a, int b) {
	return (a - b);
}

int (*choice(char c))(int, int) {
	switch (c) {
		case '+':
			return &plus;
		case '-':
			return &minus;
		default:
			return NULL;
	}
}

int execute_operation(int a, int b, int(*op)(int x, int y)) {
	return op( a , b );
}



Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 16:55
da Luke88
Mercyful ha scritto: si Luke hai ragione, però quello che sto facendo è quello che voglio fare,
vuoi accedere a memoria non allocata?
Mercyful ha scritto: mancava giusto un'altra correzione,
in effetti non ho detto come doveva comportarsi il programma, in pratica deve accedere a quelle locazioni di memoria, e il risultato deve essere giusto.
Ecco, così dovrebbe essere giusto.

Codice: Seleziona tutto

[...]
	printf("The result is: %d\n", vect[(result1 = execute_operation(5, 2, choice('-')))]);
	printf("The result is: %d\n", vect[(result = execute_operation(4, 2, choice('-')))]);
no, ti ho detto che è inutile mettere quel "result" o "result1".
fare:
printf("The result is: %d\n", vect[execute_operation(5, 2, choice('-'))]);
è uguale.
a meno che tu poi non riusi in qualche modo result e result1, ma qui non li riusi.

ragioniamo. calcoli execute_operation(5, 2, choice('-')). Questa funzione restituisce 5-2 = 3.
vect ha 2 elementi.
vect[0] = 3
vect[1] = 2
basta.
quando tu cerchi di accedere a vect[3] non accedi a qualcosa di definito! può essere qualsiasi cosa...
se vuoi che il primo printf restituisca "The result is: 3", o cambi quell'execute in:
execute_operation(2, 2, choice('-'))
oppure cambi vect in vect[4] = {0, 1, 2, 3 };

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 17:00
da Mercyful
Bhe il risultato che ottengo non è un errore, è quello che voglio ottenere e sono i valori esatti delle sottrazioni (anche se solo di quelle due).
Hai provato a far girare il programma? Restituisce perfettamente i valori 3 e 2 e non per puro caso!
Hai capito il perchè?

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 17:22
da 414N
Io sinceramente non capisco a cosa serva vect...
Non ti interessa il risultato ritornato o dalla somma o dalla sottrazione? Che ragione c'è di usare il risultato come indice all'interno di un vettore di due elementi (tra l'altro senza bound checking)?

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 17:26
da Luke88
Mercyful ha scritto:Bhe il risultato che ottengo non è un errore, è quello che voglio ottenere e sono i valori esatti delle sottrazioni (anche se solo di quelle due).
Hai provato a far girare il programma? Restituisce perfettamente i valori 3 e 2 e non per puro caso!
Hai capito il perchè?
si, l'ho capito il perchè. ma non ti sei accorto che quando accedi a vect[3] in realtà non stai accedendo al vettore ma aaccedi a result, e quando accedi a vect[2] in realtà non accedi al vettore ma accedi a result1.
sei andato in buffer overflow.
per puro c*lo result e result1 contengono i risultati rispettivamente di (4-2) e (5-2). e si trovano nella giusta posizione in memoria.
non stai usando vect. se non ci credi cambia vect in vect[2] = { 0, 0} e vedrai che "funzionerà" lo stesso.
se vuoi farlo smettere di funzionare, inserisci una qualsiasi variabile prima di vect[], ma dopo result e result1...
ad esempio:

Codice: Seleziona tutto

   int result = 0;
   int result1 = 0;
   int ciaociao[2] = {999, 1234};
   int vect[2] = {3 , 2};
e ora il primo risultato sarà 1234, e il secondo 999.

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 17:36
da Mercyful
Si lo so, ma non è per c**o che mi esce il risultato, è perchè stavo cercando di capire come mette i risultati lo stack.
I valori successivi sono si i valori di result e result1 ma non per c**o.
I valori poi che stanno dentro il vettore non li uso, sono solo per un eventuale gioco che volevo fare con l'operatore modulo.
Infatti come ho detto prima funziona solamente con quelle due sottrazioni, se vai oltre con gli indici ottieni altri risultati.
Non mi hai detto se l'hai provato, dovrebbe dare lo stesso risultato anche a te per via dello stack.
Mi sbaglio?

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 17:40
da Luke88
Mercyful ha scritto:Si lo so, ma non è per c**o che mi esce il risultato, è perchè stavo cercando di capire come mette i risultati lo stack.
I valori successivi sono si i valori di result e result1 ma non per c**o.
vabbè, ma allora dillo che l'overflow era pposta :lol:
credevo cercassi di riavere i valori di vect!
Mercyful ha scritto: I valori poi che stanno dentro il vettore non li uso, sono solo per un eventuale gioco che volevo fare con l'operatore modulo.
Infatti come ho detto prima funziona solamente con quelle due sottrazioni, se vai oltre con gli indici ottieni altri risultati.
Non mi hai detto se l'hai provato, dovrebbe dare lo stesso risultato anche a te per via dello stack.
Mi sbaglio?
l'ho provato, si...

Re: Puntatori e vettori.

Inviato: lun 13 lug 2009, 17:51
da Mercyful
Si era quello che volevo fare... non ho detto mai cosa volevo fare..
Se funziona da te è un bene funziona tutto correttamente..

grazie mille! !