PDA

View Full Version : [C] programma scambio contenuto variabili con puntatore dà segmentation fault


phantom85
11-06-2008, 14:38
Ciao a tutti,
ho scritto un breve programma in C in cui c'è una funzione che passati due interi, scambia il contenuto delle due variabili e restituisce il puntatore al valore più grande.

Ho anche scritto un main per testarlo inizializzando le variabili.

Il problema è che nell'esecuzione da shell mi dà segmentation fault, mentre sul pc di un mio amico lo stesso programma funziona.

Come mai???


ecco il codice in allegato... HELP :confused:

arcer
11-06-2008, 17:15
Ciao a tutti,
ho scritto un breve programma in C in cui c'è una funzione che passati due interi, scambia il contenuto delle due variabili e restituisce il puntatore al valore più grande.

Ho anche scritto un main per testarlo inizializzando le variabili.

Il problema è che nell'esecuzione da shell mi dà segmentation fault, mentre sul pc di un mio amico lo stesso programma funziona.

Come mai???


ecco il codice in allegato... HELP :confused:



se vuoi una funzione che scambi semplicemente due numeri puoi usare una proprieta molto carina dello XOR che è questa:

a^=b;
b^=a;
a^=b;

che vuol dire

a=a^b;
b=b^a;
a=a^b;

esempio pratico

a=5 b=2
1° step a=a^b;----> a=5^2=7 stato: a=7 b=2
2° step b=b^a;----> b=2^7=5 stato: a=7 b=5
3° step a=a^b;----> a=7^5=2 stato: a=2 b=5

CVD :P

un'implementazione della funzioncina potrebbe essere:


void scambi(int *a, int *b)
{
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
}


non restituisce nulla ma se tu passi i due numeri alla fine ti ritroverai i due numeri scambiati se vuoi che ti restituisca qualcosa metti un if e ti fai ritornare il puntatore alla variabile piu grande :P

Energy++
11-06-2008, 18:27
se vuoi una funzione che scambi semplicemente due numeri puoi usare una proprieta molto carina dello XOR che è questa:

a^=b;
b^=a;
a^=b;

che vuol dire

a=a^b;
b=b^a;
a=a^b;

esempio pratico

a=5 b=2
1° step a=a^b;----> a=5^2=7 stato: a=7 b=2
2° step b=b^a;----> b=2^7=5 stato: a=7 b=5
3° step a=a^b;----> a=7^5=2 stato: a=2 b=5

CVD :P

un'implementazione della funzioncina potrebbe essere:


void scambi(int *a, int *b)
{
(*a)^=(*b);
(*b)^=(*a);
(*a)^=(*b);
}


non restituisce nulla ma se tu passi i due numeri alla fine ti ritroverai i due numeri scambiati se vuoi che ti restituisca qualcosa metti un if e ti fai ritornare il puntatore alla variabile piu grande :P

mi piace troppo questa implementazione complimenti :)

arcer
11-06-2008, 20:56
mi piace troppo questa implementazione complimenti :)

thx all'uni con il mio prof in ste cose ci ha fatto na testa enorme :) ..cmq è buona perche è semplice, elegante ed ottimizzata perche gli operatori bitwise vengono processati molto piu velocemente rispetto alle operazioni di scambio e/o operazioni...che poi cmq con sti operatori bitwise spesso operazioni lunghissime si fanno in un paio di istruzioni del tipo invertire i numeri di una cifra il mio prof lo faceva con un'unica istruzioni usando gli operatori binari lol

phantom85
12-06-2008, 09:28
#include <stdio.h>

int *scambia (int a, int b) {
int swap, *max;
swap=a;
a=b;
b=swap;
if (a>b)
*max=a;
else
*max=b;
return max;
}


int main() {
int a=7, b=5;
printf ("Il più grande è: %d\n",scambia(a,b));
return 0;
}



per comodità te l'ho riscritto nei tag quote...

perchè scambi le variabili all'interno della funzione? quelle sono copie locali...

il puntatore max non è inizializzato... un puntatore si inizializza con un indirizzo di memoria, non con un valore...

la funzione torna un int *, quindi per accedere al valore effettivo devi fare una derefernziazione, cioè *(scambia(a,b))...

cmq la tua funzione non scambia nulla, o meglio, scambia solo i valori delle copie locali e "restituisce" (o almeno, ci prova) un puntatore ad una variabile che però verrà distrutta, in quanto è allocata sullo stack e alla chiusura della funzione quell'indirizzo che vorresti assegnarli non puoi sapere a cosa punterà...

Ringrazio tutti per l'aiuto!
Comunque il testo dell'esercizio è questo:
"Scrivete una funzione che scambi il valore di due variabili intere e restituisca un puntatore al valore massimo.
Testate la funzione richiamandola dal main del programma (non è necessario prevedere l’inserimento di input, inizaliz-
zate opportunamente le variabili per fare i test necessari)."

A questo punto cosa dovrei scrivere? L'implementazione con lo XOR è carina, ma non ce l'hanno mai spiegata, quindi non credo di poterla usare!!

gugoXX
12-06-2008, 10:14
Ti sconsiglio la soluzione degli XOR, per vari motivi.
E' peggiore sia come performance che come leggibilita' rispetto alla soluzione classica, che penso sia quella che il tuo professore vorrebbe.
Inoltre non permette di far capire se hai capito cosa vuol dire scambiare il valore di due variabili.
L'unico vantaggio della soluzione XOR e' che non fa uso di variabili d'appoggio, e sarebbe da usarsi in carenza di risorse/registri.
Cosa che oggi non capita spesso, soprattutto in un ambiente compilato dove non si ha il controllo sui registri.

phantom85
12-06-2008, 10:20
Ti sconsiglio la soluzione degli XOR, per vari motivi.
E' peggiore sia come performance che come leggibilita' rispetto alla soluzione classica, che penso sia quella che il tuo professore vorrebbe.
Inoltre non permette di far capire se hai capito cosa vuol dire scambiare il valore di due variabili.
L'unico vantaggio della soluzione XOR e' che non fa uso di variabili d'appoggio, e sarebbe da usarsi in carenza di risorse/registri.
Cosa che oggi non capita spesso, soprattutto in un ambiente compilato dove non si ha il controllo sui registri.

Grazie per il consiglio...sapresti correggere il mio codice in modo che tutto funzioni?

gugoXX
12-06-2008, 10:27
Grazie per il consiglio...sapresti correggere il mio codice in modo che tutto funzioni?

Non si possono scrivere soluzioni.
Ma pensaci bene.

Hai una bottiglia piena di vino e una piena di birra.
Devi scambiare il contenuto delle 2 bottiglie.
Hai a disposizione tante bottigile vuote quante ne vuoi.

Come fai?

arcer
12-06-2008, 10:35
Ti sconsiglio la soluzione degli XOR, per vari motivi.
E' peggiore sia come performance che come leggibilita' rispetto alla soluzione classica, che penso sia quella che il tuo professore vorrebbe.
Inoltre non permette di far capire se hai capito cosa vuol dire scambiare il valore di due variabili.
L'unico vantaggio della soluzione XOR e' che non fa uso di variabili d'appoggio, e sarebbe da usarsi in carenza di risorse/registri.
Cosa che oggi non capita spesso, soprattutto in un ambiente compilato dove non si ha il controllo sui registri.

non capisco perche sono peggiori a livello di performance :mbe: posso capire per la leggibilità ma le prestazioni :mbe:

gugoXX
12-06-2008, 10:45
non capisco perche sono peggiori a livello di performance :mbe: posso capire per la leggibilità ma le prestazioni :mbe:

Ecco qui

soluzione a XOR
3 letture da memoria
3 scritture su memoria

Nessuna possibilita' di accoppiamento istruzioni.
6 step sequenziali, che se va bene sono da 1 ciclo di clock l'uno
ma penso che lo XOR su memoria sia piu' pesante.

a ^= b;
00000026 mov eax,dword ptr [esi]
00000028 xor dword ptr [edi],eax
b ^= a;
0000002a mov eax,dword ptr [edi]
0000002c xor dword ptr [esi],eax
a ^= b;
0000002e mov eax,dword ptr [esi]
00000030 xor dword ptr [edi],eax



Soluzione classica
2 letture da memoria
2 scritture su memoria
1 copia di registro

Possibilita' di accoppiamento alta
Tutte le istruzioni sono sicuramente da 1 ciclo di clock

int c = a;
00000028 mov eax,dword ptr [esi]
0000002a mov ebx,eax
a = b;
0000002c mov eax,dword ptr [edi]
0000002e mov dword ptr [esi],eax
b = c;
00000030 mov dword ptr [edi],ebx

arcer
12-06-2008, 10:50
Ecco qui

soluzione a XOR
3 letture da memoria
3 scritture su memoria

Nessuna possibilita' di accoppiamento istruzioni.
6 step sequenziali, che se va bene sono da 1 ciclo di clock l'uno
ma penso che lo XOR su memoria sia piu' pesante.

a ^= b;
00000026 mov eax,dword ptr [esi]
00000028 xor dword ptr [edi],eax
b ^= a;
0000002a mov eax,dword ptr [edi]
0000002c xor dword ptr [esi],eax
a ^= b;
0000002e mov eax,dword ptr [esi]
00000030 xor dword ptr [edi],eax



Soluzione classica
2 letture da memoria
2 scritture su memoria
1 copia di registro

Possibilita' di accoppiamento alta
Tutte le istruzioni sono sicuramente da 1 ciclo di clock

int c = a;
00000028 mov eax,dword ptr [esi]
0000002a mov ebx,eax
a = b;
0000002c mov eax,dword ptr [edi]
0000002e mov dword ptr [esi],eax
b = c;
00000030 mov dword ptr [edi],ebx




azz grande....non ci avevo mai pensato....queste cose le hai fatte con un semplice debugger no?

shinya
12-06-2008, 10:50
thx all'uni con il mio prof in ste cose ci ha fatto na testa enorme :) ..cmq è buona perche è semplice, elegante ed ottimizzata perche gli operatori bitwise vengono processati molto piu velocemente rispetto alle operazioni di scambio e/o operazioni...che poi cmq con sti operatori bitwise spesso operazioni lunghissime si fanno in un paio di istruzioni del tipo invertire i numeri di una cifra il mio prof lo faceva con un'unica istruzioni usando gli operatori binari lol

Wow! Spero di non doverci mai lavorare con uno cosi!

Edit: ecco, dopo aver visto la risposta di gugo aggiungerei:"Visto a voler fare il figo, professore universitario?"

gugoXX
12-06-2008, 11:12
azz grande....non ci avevo mai pensato....queste cose le hai fatte con un semplice debugger no?

Il disassembler di visual studio.

Premature optimization is the root of all evil
http://en.wikipedia.org/wiki/Unix_philosophy

phantom85
12-06-2008, 11:30
Non si possono scrivere soluzioni.
Ma pensaci bene.

Hai una bottiglia piena di vino e una piena di birra.
Devi scambiare il contenuto delle 2 bottiglie.
Hai a disposizione tante bottigile vuote quante ne vuoi.

Come fai?


Non è lo stesso principio secondo cui ho utilizzato la variabile swap?