Newsgroup: it.comp.lang.c
Titolo: swap(x,y)

sul k&r al capitolo 4 (esercizio 4.9) si chiede di fare una macro swap(x,y)
sinceramente non sono riuscito a creare una m,acro con solo due parametri in
ingresso...
es se scrivo:
#define SWAP(a,b,c) c=a,a=b,b=c va tutto bene quando la richiamo, 
es se scrivo:
#define A 0
#define B 0
#define C 0
#define SWAP(A,B,C) C=A,A=B,B=C va tutto bene quando la richiamo
ma se voglio utilizzare la macro come scrive il k&r e quindi scrivo
#define temp 0
#define SWAP(a,b) temp=a,a=b,b=temp e compilo con il vc++ 
ho un errore: error C2106: '=' : left operand must be l-value
e' possibile fare questa macro con soli due argomenti???
ciao e grazie in anticipo!!!
-- 
Posted from  [213.82.129.50] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 #define SWAP(a,b) temp=a,a=b,b=temp e compilo con il vc++
#define SWAP(a,b) {int temp; temp=a;a=b;b=temp;} // a e b devono essere
int!!!!!

Toglimi una curiosita', quanto tempo hai impiegato per imparare il c bene 
(intendo BENE)??? 
io oramai e' da un bel po che lo utilizzo , ci faccio programmi che 
funzionano bene (quasi sempre) eppure 
mi rendo conto che ancora ho delle LACUNE PAZZESCHE!!!
non credo che il problema sia nell'averlo studiato con il Guidi e Bellini
(che secondo me in alcuni punti sono piu' chiari del k&r,vedi direttive 
del precompilatore...)
secondo me ci vogliono due anni buoni o forse ci vogliono due anni per chi 
come me purtroppo ha iniziato a programmare con il vb...
ciao e grazie della risposta!!!


 (intendo BENE)???
Lo faccio da 15 anni, e non mi permetto di dire di saperlo bene... :-)
Molto importante, secondo me, di non accontentarsi mai con una soluzione
solo.
Di mettere in questione la propria soluzione e trovare soluzioni piu'
eleganti, facili...
Cercare di capire in fondo cosa succede nel codice (non soltanto avere una
idea
vaga), anche a livello di macchina.
Scrivere codice sempre chiaro, senza trucchi. (infatti lo SWAP come
definizione
al posto di una funzione potrebbe essere efficiente, ma non e' proprio
chiaro:
prova a steppare il codice con un debugger...).
J.

 wrote:
: #define SWAP(a,b) temp=a,a=b,b=temp e compilo con il vc++ 
: ho un errore: error C2106: '=' : left operand must be l-value
: e' possibile fare questa macro con soli due argomenti???
: ciao e grazie in anticipo!!!
define SWAP(A,B) A ^= B ^= A ^= B;
senza variabili di appoggio ;)
tre belle XORate una via l'altra e il gioco e' fatto... ;)
-- 
  --==> ALoR <==---------------------- -  -   -
  ettercap project: 
http://ettercap.sourceforge.net
  e-mail: alor (at) users (dot) sourceforge (dot) net    

 tre belle XORate una via l'altra e il gioco e' fatto... ;)
 
  ....quando leggo queste cose vado in depressione!!!


 tre belle XORate una via l'altra e il gioco e' fatto... ;)
Ti ricordi per caso la soluzione che usa solo sottrazione e addizione?
J.

L'avevo vista anche implementato cosi' in modo che non risenta del
tipo delle variabili da swappare :)
<CODE>
#DEFINE SWAP(tipo, a, b) {tipo temp; temp = a; a = b; b = temp}
</CODE>
Questa invece (#define SWAP(A,B) {A ^= B ^= A ^= B;} ) non l'avevo
ancora vista, me la devo studiare meglio :)
Bye, Paolo :)

e' possibile fare questa macro con soli due argomenti???
#define SWAP(a,b) { int t = a; a = b; b = t; }
In ogni caso, non usare mai le macro, usa sempre le
funzioni.
Che versione del K&R possiedi ? I o II ?
--
Andrea Laforgia - walkietalkie(at)
libero.it
http://www.geocities.com/AndreaLaforgia

senza variabili di appoggio ;)
Non e' portabile (ci sono piattaforme sotto le quali non
avviene affatto uno scambio dei valori).
In ogni caso, per ragioni di leggibilita' del codice, e'
meglio utilizzare tre statement separati con una variabile
d'appoggio temporanea.


 Non ho capito bene se lo chiedevi a me comunque ho una copia originale del
1978, me l'ha data il capoprogetto della societa' per la quale sono andato a
lavorare, se sei di roma ed hai intenzione di vederla scrivimi in privato,
ciao


se sei di roma ed hai intenzione di vederla scrivimi in privato,
No, grazie, posseggo tutte e due le versioni originali.


 Ti ricordi per caso la soluzione che usa solo sottrazione e addizione?
a = b - a
b = b - a   ->>  che sarebbe b - ( b - a ) --> cioe'  a
a = a + b  ->> che sarebbe ( b - a ) + a --> cioe' b
non lo scrivo in C altrimenti Laforgia avrebbe da ridire sicuramente sul mio stile...  ;)
quindi la traduzione da alto livello al C fatela voi... :)
ciao a tutti tranne ad Andrea Laforgia... ;) heheh ( pace fatta ? o sei ancora incazzato ? )
bye

 avviene affatto uno scambio dei valori).
qua mi spiace ma hai tirato la bomba !!!
XOR e' un operatore logico.  e la logica dice che tre XOR uno di seguito all'altro hanno l'effetto di scambiare i valori.
se poi tu hai processori con la ALU (algebric LOGIC unit) che sbaglia non e' colpa mia !!
ora, visto che sei tanto sicuro di te, dammi un esempio di piattaforma dove l'XOR non funziona !!
p.s. ho capito che ora ti accanirai contro di me ogni cosa che scrivero, ma questa era troppo grossa !!
scendi dal piedistallo, professore !!
in rete siamo tutti uguali !
bye

ogni cosa che scrivero, ma questa era troppo grossa !!
p.s.: setta il tuo newsreader perche' tagli le righe a non
piu' di 72 colonne, leggere i tuoi messaggi con righe
lunghissime e' molto fastidioso e fuori standard.
Non commento i tuoi giudizi su di me, ne' ho la minima
intenzione di accanirmi su di te, ho ben altro da fare.
Per quanto questa cosa ti possa dispiacere, non sei cosi'
importante.
Cerca di scrivere cose corrette se vuoi sentirti in grado di
suggerire una strada per le altre persone, altrimenti crei
solo casini.
Ti saluto con amicizia.


tre belle XORate una via l'altra e il gioco e' fatto... ;)
Questo codice ha un bel po' di problemi:
- Non e' portabile: non e' permesso modificare una
  stessa variabile piu' di una volta prima di un
  sequence point. A viene modificata due volte in
  quella espressione e questo significa invocare i
  demoni nasali.
- La macro non racchiude gli argomenti fra parentesi
  e questo puo' portare problemi nel caso di
  passaggio di espressioni
- La macro contiene un ';' finale e questo crea
  molti problemi (es. se SWAP viene usata in una 'if'
  senza che sia protetta fra graffe)
- La cosa non funziona se provi a scambiare una
  variabile con se stessa
- Quando anche dovesse funzionare con un particolare
  compilatore questo codice e' comunque molto
  inefficiente se paragonato ad una SWAP che usi
  una variabile di appoggio
Riassumendo lo scambio con triplo-xor non ha *NESSUN*
senso in programmi seri nemmeno quando viene scritto
in forma corretta (cosa che non hai fatto).
L'unica ragione per cui ha qualche senso nelle "barzellette"
e' quello che aiuta a scrivere codice di difficile lettura.
Dimostrare attaccamento *reale* a questa cosa e' secondo
me indice di grave immaturita' (dal punto di vista della
programmazione).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

ancora vista, me la devo studiare meglio :)
Lasciala perdere... non e' codice C portabile e anche quando
dovesse essere scritta in maniera corretta rappresenta comunque
un *pessimo* modo di scambiare due variabili.
HTH


  ....quando leggo queste cose vado in depressione!!!
E fai male... chi ha scritto quella cosa ha riportato un
esempio errato. Quel codice non e' codice C portabile e
anche quando viene scritto in forma corretta e' una vera
schifezza sotto tutti i punti di vista.


  do { tipo temp_=(a); (a)=(b); (b)=temp_; } while(0)
Gia', ci avevo pensato, ma alla fine mi sono detto erroneamente che
non serviva la parentesi e non l'avevo messa :P
Una curiosita': cosa cambia da
#define MACRO(parametri) {...}
a
#define MACRO(parametri) do {...} while(0)
? In particolare perche' dici che e' pericolosa usando le graffe in
quel modo? So che viene preferita la versione con il do while, ma non
so perche'.
bye, Paolo :)

so perche'.
Perche' usando do-while la chiamata di macro puo'
essere usata come se fosse una chiamata di funzione
senza avere fastidiosi problemi con i ';'.
Mi spiego meglio.
In C scrivendo
  { ... };
hai scritto *due* statement consecutivi. Il primo e' un
blocco (quello racchiuso fra graffe) mentre il secondo
e' lo "statement vuoto". Questo implica che se scrivi
  if (...)
    SWAP(x,y);
  else
    ...
allora nel caso che SWAP sia la tua versione di macro
il preprocessore tradurra' il tutto in
  if (...)
    { ... } ;
  else
    ...
e di conseguenza il codice generato non e' codice valido
C perche' viene interpretato come:
  if (...)
    { ... }
  ;       /* <-- statement vuoto; if terminato */
  else    /* <-- Errore di sintassi: else senza if */
Usando invece la forma do-while il problema non c'e'
perche' in C
   do { ... } while(0);
e' *un solo* statement (di tipo do-while) e quindi
viene interpretato correttamente anche nel caso
che si trovi in un if/else. L'espansione in questo
caso infatti porta ad avere:
  if (...)
    do { ... } while (0); /* <-- singolo statement */
  else
    ... /* <-- parte else di questo if */
Il codice "do { ... } while(0)" e' equivalente
all'aver messo solo la parte fra graffe e tutti i
compilatori moderni non avranno nessun problema ad
accorgersi che il test finale per una eventuale
ripetizione del blocco puo' essere tranquillamente
eliminato visto che la condizione non potra' mai
verificarsi (e' una espressione costante).


 solo casini.
cerca di astrarre in po' di piu' da quello che e' il mero C e il suo stile.
da quello che vedo, qui e' pieno di gente che non ha nemmeno idea
di cosa sia il C e che chiede come di facciano i compiti per casa...
mi sembra inutile star qui a puntualizzare sullo stile perfetto.
ciao

 programmazione).
attaccamento alla logica che sta dietro... era tutto qui il mio intento !
far sapere a chi non lo sapesse che la logica aiuta a risolvere meglio i 
problemi.
mi pare strano che non mi abbiate contestato anche l'esempio con 
le sottrazioni e l'addizione...
dora in poi scrivero' tutto ad alto livello, cosi' voi puristi del C non sprecherete
tempo a correggere lo stile di noi poveri ignoranti e immaturi...
ciao

cerca di astrarre in po' di piu' da quello che e' il mero C e il suo stile.
Aridalle... non e' una questione di STILE, e' una questione
di CORRETTEZZA del codice.
Tu hai scritto un codice sbagliato e ti e' stato fatto
presente che e' sbagliato.
Ammetti i tuoi sbagli, senza forzare la mano e vivrai piu'
tranquillo.
Punto e basta.


tempo a correggere lo stile di noi poveri ignoranti e immaturi...
Non si corregge lo stile, si correggono gli sbagli, e'
questo che non hai ancora capito.


 La logica si puo' dimostrare anche per passi successivi.
ok, allora spezzalo in tre passi, metti le parentesi, i do { } while(0) e tutto quello che ti pare, 
ma il concetto resta sempre lo stesso.
bye

ma il concetto resta sempre lo stesso.
Guarda che questo lo sapevamo tutti, ancor prima che ce lo
dicessi tu.


 e', quindi, "undefined behavior".
Questo non lo sapevo. Quindi, se ho capito bene, anche una cosa come 
a = a++;
e` illegale, giusto?
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Il dottore mi ha detto di smettere di fare cene intime per quattro.
A meno che non ci siamo altre tre persone.

 dicessi tu.
e allora perche' mi siete saltati in testa ?
cmq non tutti lo sapevano, e spero che sia servito a qualcuno.
bye

e` illegale, giusto?
Si'.


 e` illegale, giusto?
   Nel linguaggio C, purtroppo o per fortuna, ben poco e` illegale: lo 
standard [1] si limita a marcare /statement/ del tipo in esame come 
"indefiniti".
   Per la gioia di grandi e piccini, ed in particolare di alcuni 
professionisti dei vincoli di programmazione (<grin>), dunque, la 
definizione per i costrutti del genere e` splendidamente lasciata agli 
implementatori dei compilatori che, industrialmente parlando, fanno come 
loro pare.
   Il seguente frammento, per esempio, compila ed esegue come 
logicamente atteso con il gcc 2.95.3-5 (cygwin special).
<code>
	#include <stdio.h>
	int
	main(void)
	{
		int a=1;
		a=a++;
		printf("%d\n",a);
		return 0;
	}
</code>
   Nulla esclude, e lo standard men che meno, che altri compilatori si 
comportino in modo differente, facendo, per esempio, uscire i demoni dal 
naso di Kaz Kylheku.
   Ora, la domanda che bisogna porci e`: ci sentiamo veramente tanto 
crudeli da scrivere codice in grado di torturare cosi` ferocemente il 
nostro /regular/ di news:comp.lang.c oppure preferiamo cavallerescamente 
attenerci a cio` che un'organizzazione saggia come l'ISO ha deciso di 
raccogliere in uno standard?
   Ai programmatori l'ardua sentenza...
--
Alla prossima,
Marco
Reference:
[1] INTERNATIONAL STANDARD ISO/IEC 9899 (Programming languages -- C),
     article 6.5.2 and footnote #70, page 67.

 "indefiniti".
   Aggiungerei che tutto l'accademico... scazzo apparso in questi ultimi 
giorni e` irreverentemente reso superfluo da una caratteristica mutuata 
dal C++ da molti compilatori C ed ora compresa anche nello standard, 
ovvero lo specificatore di funzione *inline*, il quale rende le 
successive chiamate alla funzione cosi` dichiarata "as fast as 
possible", vale a dire, per la maggior parte dei compilatori 
efficentemente moderni, come una macro di pre-compilazione.
   Alle volte, inoltre, si possono ottenere risultati sorprendenti: i 
deu frammenti di codice seguenti, per esempio, ottengono tempi di 
esecuzione  dello stesso ordine di grandezza (dal mio host multitasking 
non posso pretendere di piu`...).
<code name="swap1.c">
	inline void
	swap(int *a, int *b)
	{
		int temp;
 
		temp=*a;
		*a=*b;
		*b=temp;
	}
	int
	main(void)
	{
		int a,b;
		int i;
		for(i=0;i<1000000;i++) {
			a=i;
			b=-a;
			swap(&a,&b);
		}
 
	return 0;
}
</code>
<code name="swap2.c">
	#define swap(a,b) { int temp=(a);(a)=(b);(b)=temp; }
	int
	main(void)
	{
		int a,b;
		int i;
 
		for(i=0;i<1000000;i++) {
			a=i;
			b=-a;
			swap(a,b)
		}
 
		return 0;
	}
</code>


poveri ignoranti e immaturi...
Tutti noi programmatori siamo rimasti colpiti dal triplo XOR
la prima volta che lo abbiamo visto ... te lo posso garantire.
Pero' e' importante riuscire a superare la fase dello stupore
e arrivare a delle conclusioni sensate. Quel codice e' buono
come battuta o barzelletta ma non serve praticamente a niente.
Io sono rimasto deluso da due cose presenti nei tuoi post:
 - Non ti sei preso la briga di verificare il problema
   della portabilita' di quel codice nemmeno dopo una
   segnalazione al riguardo.
   Probabilmente non hai mai sentito parlare di sequence
   point e altro "avvocatese" dello standard e forse non
   hai mai letto il documento dello standard o qualche
   draft dello stesso. Ma classificare il compilatore Sun
   come "storpio" perche' non fa funzionare il tuo codice
   (che e' non portabile) e' abbastanza puerile.
   Prima almeno informati.
   Il tuo codice non e' sbagliato perche' lo dico io,
   perche' lo dice La Forgia o perche' lo dice qualcun
   altro che ti sta antipatico. E' sbagliato perche' lo
   dice lo standard "C" che sul linguaggio "C" e' chi ha
   l'ultima parola. Non c'e' niente di soggettivo.
   E' sbagliato e basta. Cosa e' il linguaggio "C" e'
   per *definizione* quello che sta scritto su quel
   documento. Punto. Niente se e niente ma.
 - Non capisco perche' hai affermato il falso quando hai
   parlato del codice assembler generato. Tu la prova non
   credo che l'abbia fatta, vero ? Perche' contare palle ?
   Potevi spendere meglio il tuo tempo facendo la prova
   e meditandoci sopra. Io ho lavorato con un po' di
   processori diversi e non mi viene in mente nessun caso
   in cui per scambiare due variabili abbia senso fare il
   triplo XOR. Se invece la prova l'hai fatta davvero
   allora mi scuso e vorrei sapere con che compilatore
   e quale sorgente hai compilato. C'e' sempre da imparare.


   perche' lo dice La Forgia o perche' lo dice qualcun
Mi sono reso conto solo ora che il cognome e' Laforgia.
Chiedo scusa per l'errore :)


Chiedo scusa per l'errore :)
Fa niente, ci sono abituato ;)
p.s.: il tuo sito non funziona piu' ? 
e' diventato il mio riferimento per il gioco della retina
elastica ;)


    e quale sorgente hai compilato. C'e' sempre da imparare.
sistema operativo LINUX
compilatore GCC
esempio con var temporanea:
0x80483ac <main+20>:    mov    0xfffffffc(%ebp),%eax
0x80483af <main+23>:    mov    %eax,0xfffffff4(%ebp)
0x80483b2 <main+26>:    mov    0xfffffff8(%ebp),%eax
0x80483b5 <main+29>:    mov    %eax,0xfffffffc(%ebp)
0x80483b8 <main+32>:    mov    0xfffffff4(%ebp),%eax
0x80483bb <main+35>:    mov    %eax,0xfffffff8(%ebp)
esempio con XOR:
0x80483ac <main+20>:    mov    0xfffffff8(%ebp),%eax
0x80483af <main+23>:    xor    %eax,0xfffffffc(%ebp)
0x80483b2 <main+26>:    mov    0xfffffffc(%ebp),%eax
0x80483b5 <main+29>:    xor    %eax,0xfffffff8(%ebp)
0x80483b8 <main+32>:    mov    0xfffffff8(%ebp),%eax
0x80483bb <main+35>:    xor    %eax,0xfffffffc(%ebp)
l'esempio sotto PA-RISC ero in ufficio, e fino a lunedi' non te lo posto, ma era simile...
cmq come vedi le istruzioni sono 6 in entrambi i casi, ma quello con 
XOR accede a memoria la meta' delle volte !
in effetti i tuoi disasseblati mi danno torto, ma io mi basavo su questi quando l'ho scritto.
ciao !


beh... oddio... forse e' meglio dire usa 3 MOV in meno...
e da quel che mi ricordo MOV e' un istruzione molto piu' lenta di AND OR XOR ecc...
(se ho detto la cazzata, uccidetemi pure...)
bye

 naso di Kaz Kylheku.
Scusami se da un OT ne creo un altro... quest'espressione da dove
nasce??, l'ho già sentita un paio di volte.
--
And the main in the rain picked up his bag of secrets, and journeyed
up the mountainside, far above the clouds, and nothing was ever heard
from him again, except for the sound of tubular bells.
BlackDemon - 
bde...@dominio.it
per mandarmi un'e-mail scrivi 'iol' invece di 'dominio'

 Risultati compilazione g++ (*)
Per la cronaca, sulla funzione SWAP3 gcc 3.0.1 dice:
warning: operation on `a' may be undefined
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Software is like sex; it's better when it's free.
Linus Torvalds

basavo su questi quando l'ho scritto.
Sono convinto che anche i *tuoi* disassemblati ti diano
torto se le prove le fai seriamente. Fai il piacere a
me (e soprattutto a te stesso) di andare a fondo della
questione e di risolvere il dubbio una volta per tutte.


 questione e di risolvere il dubbio una volta per tutte.
ok. basta. sono convito. non faccio ulteriori prove.
sono sicuro che con gcc -O2 il codice sara' ottimizzato.
chissa' invece come si comporta con la versione "sottrai e somma" ?
ti va di fare delle prove ?
ciao !