Puntatori e vettori.

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Puntatori e vettori.

Messaggio 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!!

Avatar utente
robbybby
Linux 4.x
Linux 4.x
Messaggi: 1223
Iscritto il: sab 16 dic 2006, 10:48
Slackware: 13.1 / 64 bit
Kernel: 3.3.x
Desktop: KDE 4.4.5
Località: Fra Trantor e Terminus

Re: Puntatori e vettori.

Messaggio 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.

Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Re: Puntatori e vettori.

Messaggio 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.

Avatar utente
Luke88
Linux 3.x
Linux 3.x
Messaggi: 624
Iscritto il: mer 7 set 2005, 0:00
Slackware: 13.0
Kernel: 2.6.30-zen4
Desktop: xfce4
Località: Udine

Re: Puntatori e vettori.

Messaggio 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"
Ultima modifica di Luke88 il dom 12 lug 2009, 21:39, modificato 1 volta in totale.
Meeting efficency = Average_Intelligence/( Number_Of_People^2 )

Avatar utente
m0rdr3d
Linux 2.x
Linux 2.x
Messaggi: 404
Iscritto il: dom 24 dic 2006, 13:40
Slackware: Slackware64-current
Kernel: 3.4.*
Desktop: KDE 4.8.2

Re: Puntatori e vettori.

Messaggio 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

Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Re: Puntatori e vettori.

Messaggio 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 );
}


Avatar utente
Luke88
Linux 3.x
Linux 3.x
Messaggi: 624
Iscritto il: mer 7 set 2005, 0:00
Slackware: 13.0
Kernel: 2.6.30-zen4
Desktop: xfce4
Località: Udine

Re: Puntatori e vettori.

Messaggio 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
Meeting efficency = Average_Intelligence/( Number_Of_People^2 )

Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Re: Puntatori e vettori.

Messaggio 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 );
}



Avatar utente
Luke88
Linux 3.x
Linux 3.x
Messaggi: 624
Iscritto il: mer 7 set 2005, 0:00
Slackware: 13.0
Kernel: 2.6.30-zen4
Desktop: xfce4
Località: Udine

Re: Puntatori e vettori.

Messaggio 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 };
Meeting efficency = Average_Intelligence/( Number_Of_People^2 )

Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Re: Puntatori e vettori.

Messaggio 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è?

Avatar utente
414N
Iper Master
Iper Master
Messaggi: 2924
Iscritto il: mer 13 feb 2008, 16:19
Slackware: 15.0
Kernel: 5.15.19
Desktop: KDE5
Località: Bulagna
Contatta:

Re: Puntatori e vettori.

Messaggio 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)?

Avatar utente
Luke88
Linux 3.x
Linux 3.x
Messaggi: 624
Iscritto il: mer 7 set 2005, 0:00
Slackware: 13.0
Kernel: 2.6.30-zen4
Desktop: xfce4
Località: Udine

Re: Puntatori e vettori.

Messaggio 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.
Meeting efficency = Average_Intelligence/( Number_Of_People^2 )

Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Re: Puntatori e vettori.

Messaggio 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?

Avatar utente
Luke88
Linux 3.x
Linux 3.x
Messaggi: 624
Iscritto il: mer 7 set 2005, 0:00
Slackware: 13.0
Kernel: 2.6.30-zen4
Desktop: xfce4
Località: Udine

Re: Puntatori e vettori.

Messaggio 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...
Meeting efficency = Average_Intelligence/( Number_Of_People^2 )

Avatar utente
Mercyful
Linux 1.x
Linux 1.x
Messaggi: 196
Iscritto il: ven 25 lug 2008, 18:20
Nome Cognome: Ilario Pittau
Slackware: 13.0
Kernel: 2.6.29.6-generic
Desktop: xfce 4.6
Località: Torino

Re: Puntatori e vettori.

Messaggio 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! !

Rispondi