Newsgroup: it.comp.lang.c
Titolo: aiuto su n++ e ++n

Salve a Tutti.
Ecco il mio problema : non riesco a capire effettivamente se in un ciclo
while o in una qualsiasi altra "condizione", utilizzando la sintassi in
oggetto venga o meno incrementata la variabile.
Esempio ; sul mio libro di c c'è questa funzione
int togli_spazi (l)
char *l;
(
  int i,j;
  char *c;
  i=j=0;
  c=l;
  while (*l++ != '\0') j++;
  l-=2;
  if (j=0) return 0;
  while (l>c && l==' ') l--;
  *(++l) = '\0';
  return ( int (l-c));
)
che dovrebbe togliere gli spazi ad una stringa e restituirne la lunghezza .
Il libro spiega che l viene decrementato di 2 unità  dopo il primo while
peche' l'ultimo
carattere e' il null mentre il penultimo e' il newline.
Ma l++ nel while non aumenta LO STESSO il valore di l , dopo averlo
"passato" alla verifica della condizione ( e quindi per puntare ad un
"carattere" dovrei sottrarre ad l il valore 3 anziche' 2 dato che questo
dovrebbe puntare ad una locazione di menoria "fuori" dalla stringa)? 
Cioe' e' vero che il controllo e'  effettuato su di un determinato valore
di l
ma , a mio parere , e' altrettanto vero che l aumenta ulteriormente di uno.
E quindi mi chedo : l'aumento di l e' propedeutico al verifivarsi della
condizione o no ?
In questo caso QUANDO avviene l'aumento di L.
Stesso problema anche per queste condizioni 
while (n++ >=0) <istruzione> ;
il valore di n , se la condizione è falsa, e' aumentato o no di uno ??
i=2;
if (i++ = 4) <istr>;
a quanto e' uguale i all' uscita di questo controllo ?
ed ancora 
while ( (*cq++ = *cp++) );      con cp e cq stringhe
alla fine cq e cp punteranno alla locazione di memoria "dopo" il null
(visto che comunque c'e' prima l'asseganzione del '\0' e poi il controllo
per l'uscita dal while).
Rispondete sul NG , grazie.
P.S. Ho pochi problemi se al posto di a++ ho ++a perche' "forzo"
l'incremento (giusto?) 
-- 
Saluti 
Antonio.
E-mail   
adel...@media.cesvitec.it
(spammatemi pure tanto questo e-mail lo do a "bau" ed "oink").

 scritto nell'articolo
<01be505b$39018700$LocalHost@mc1360>...


Il Piocco (A.de Lucia) (
adel...@innocent.com
) wrote:
[ snip ]
: Esempio ; sul mio libro di c c'è questa funzione
Buttalo via, quel libro !
: int togli_spazi (l)
: char *l;
: (
:   int i,j;
:   char *c;
:   i=j=0;
:   c=l;
:   while (*l++ != '\0') j++;
:   l-=2;
:   if (j=0) return 0;
:   while (l>c && l==' ') l--;
                  ^^^^^^
Attenzione, forse hai copiato male, ma qui dev'essere 
   *l == ' '
:   *(++l) = '\0';
:   return ( int (l-c));
: )
Ma hai notato che 'i' non e' mai utilizzata e che 'j' non serve ?
Giusto per curiosita', qual'e' il titolo dell'orrendo libro che hai
la sfortuna di utilizzare ?
: Il libro spiega che l viene decrementato di 2 unità  dopo il primo while
: peche' l'ultimo carattere e' il null mentre il penultimo e' il newline.
Il '\n' non c'entra nulla. Come hai gia' capito da solo, il
decremento di 2 serve per saltare il solo '\0'.
[ snip ]
: while (n++ >=0) <istruzione> ;
: il valore di n , se la condizione è falsa, e' aumentato o no di uno ??
Si.
[ snip ]
: while ( (*cq++ = *cp++) );      con cp e cq stringhe
: alla fine cq e cp punteranno alla locazione di memoria "dopo" il null
Se cp e cq sono 'char *', si.
Ciao ciao
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

l'incremento (giusto?) 
Be' dipende ! le due cose non sono intercambiabili ! 
L'unico caso in cui non fa differenza e' quello di un'istruzione singola del
tipo
  ++a;
o
  a++;
in quanto, proprio perche' costituisce un'istruzione singola, non e' soggetta a
priorita' rispetto ad altre istruzioni.
Andrea, mica uno qualunque...
--------------------------------------------------
"Ho cambiato signature, si vede ?" 
--
Posted from 
itaca.ulysse.it
 [195.223.254.1]
via Mailgate.ORG Server - 
http://www.mailgate.org

 che dovrebbe togliere gli spazi ad una stringa e restituirne la lunghezza
Con le correzioni di cui sopra pare che faccia proprio questo ma solo
per quanto riguarda gli spazi in coda.
EMG

a quanto e' uguale i all' uscita di questo controllo ?
Necessariamente a 5, se <istr> non lo modifica.
Alex

Alex Martelli (
al...@magenta.com
) wrote:
: Il Piocco (A.de Lucia) wrote in message
: <01be505b$39018700$LocalHost@mc1360>...
[ snip ]
: >i=2;
: >if (i++ = 4) <istr>;
: >a quanto e' uguale i all' uscita di questo controllo ?
Qui c'e' qualcosa che non va...parli di controllo, ma
hai scritto un'assegnazione.
Se intendevi
int i = 2;
....
if(i++ == 4) <istr>;
...
allora dopo il controllo i vale 3 (ovviamente <istr> non viene 
eseguita).
: Necessariamente a 5, se <istr> non lo modifica.
Cough, cough...ahem ;) questo e' sbagliato, AFAIK. 
In effetti 'i++' non e' un lvalue, e l'espressione 'i++ = 4' 
da' un errore in fase di compilazione...


Enrico Maria Giordano (
fn02...@flashnet.it
) wrote:
[ snip ]
: >   *(++l) = '\0';
: In questo caso c'è un preincremento. Ecco la sequenza delle operazioni:
: 1. Viene incrementata la variabile l.
: 2. Viene applicato l'operatore asterisco alla variabile l.
: 3. Il carattere risultante viene confrontato con il '\0'.
ERRATA CORRIGE 8)
3. Al carattere risultante viene assegnato il valore '\0'.
[ snip ]
: Questa sintassi di cast è valida (ma il tipo di cast in se è obsoleto)
: in C++. In C si deve scrivere
: return ( (int)(l-c));
Domanda: ma il cast e' necessario ? AFAIK, il risultato di 
un'operazione di sottrazione tra due puntatori che puntano 
a elementi di uno stesso vettore e' un intero (con segno).


>a quanto e' uguale i all' uscita di questo controllo ?
...ops... attento !
L'istruzione 
if (i++ = 4)  ...
non e' consentita !
Penso che nel tuo programma sia 
if (i++ == 4) ... ed in tal caso il suo valore e' 3 e il ciclo non si attiva, in
quanto corrisponde a
if (i == 4) { i++; <istruzione> } else i++;
Il caso 
if (i++ = 4) 
non e' consentito in quanto "i++" (cosi' come "++i") non costituisce un
"lvalue", cioe' quel qualcosa che sta dalla parte sinistra dell'operazione di
assegnazione e che indica al compilatore dove il dato che viene assegnato deve
essere memorizzato.
Scrivere if (i = 4) e' valido, per quanto il controllo non abbia un senso
pratico rilevante, in quanto i e' un "lvalue" ("i" in questo caso assume per il
compilatore una indicazione di locazione di memoria).
In pratica, scrivere 
if (i++ = 4) equivale a scrivere if (i = 4 = i + 1) il che non ha senso in
quanto 4 non e' un "lvalue".
(anche if (++i = 4) non avrebbe senso in quanto sarebbe if (i = i + 1 = 4) )
Le assegnazioni multiple in C sono possibili, ma solo del tipo 
<variabile> = <variabile> = ... = <variabile> = <espressione> 
in cui e' necessario che le prime tre da sinistra a destra siano "lvalue" mentre
l'ultima no.
Non ci puo' essere un passaggio del tipo 
<variabile> = <espressione> = <espressione>
Come avviene invece nel tuo caso.
La distinzione tra "lvalue" e "rvalue" in C motiva perche' e' consentito
scrivere 
k = 2;
ma non 
2 = k;
In ogni caso penso che nel controllo ci sia un "==" e non un "=", altrimenti il
tuo compilatore ti avrebbe gia' segnalato la cosa con un "fatal error".


a elementi di uno stesso vettore e' un intero (con segno).
E` un ptrdiff_t, che e` un tipo integrale (con segno, si`)
dipendente dall'implementazione; potrebbe, in una data
implementazione C standard, essere piu` lungo di int (ma,
naturalmente, a rigor di standard il cast non occorre anche
in questo caso: il troncamento, o "decadimento" che dir
si voglia, deve comunque avvenire correttamente).
Ad esempio, su Alpha (ad esempio con Digital Unix, ma,
credo, anche con Linux ecc), un puntatore e` di 64 bit,
un int di 32; come ptrdiff_t hanno dunque scelto long,
che e` pure di 64 bit.
Alex

da' un errore in fase di compilazione...
Hai ragione, avevo "visto" quel che l'autore certo
intendeva (==), non quel che aveva scritto (=)!-)
Alex

 l'incremento (giusto?)
Invece di problemi ne avresti altri in quanto la variabile verrebbe
incrementata prima di essere utilizzata e quindi sarebbe tutto sballato.
Dovresti rivedere la logica del programma.
EMG

 Necessariamente a 5, se <istr> non lo modifica.
Sicuramente hai dato per scontato che fosse un loop mentre invece è un
semplice if. Ma forse l'amico Piocco intendeva proprio un loop.
EMG

...
:     [snip]
: >
: >: return ( (int)(l-c));
: >
: >Domanda: ma il cast e' necessario ? AFAIK, il risultato di
: >un'operazione di sottrazione tra due puntatori che puntano
: >a elementi di uno stesso vettore e' un intero (con segno).
: E` un ptrdiff_t, che e` un tipo integrale (con segno, si`)
: dipendente dall'implementazione; potrebbe, in una data
: implementazione C standard, essere piu` lungo di int (ma,
: naturalmente, a rigor di standard il cast non occorre anche
: in questo caso: il troncamento, o "decadimento" che dir
: si voglia, deve comunque avvenire correttamente).
OK, grazie mille.
: Ad esempio, su Alpha (ad esempio con Digital Unix, ma,
: credo, anche con Linux ecc), un puntatore e` di 64 bit,
: un int di 32; come ptrdiff_t hanno dunque scelto long,
: che e` pure di 64 bit.
[ quanto segue e' relativo a Linux, kernel 2.0.xx ]
Non vorrei sbagliare, ma mi sembra di ricordare che su
Alpha gli int sono di 64 bit.
Per quanto riguarda la piattaforma x86, ho trovato:
[root@fokhouse /root]# grep ptrdiff_t /usr/include/{linux,asm}/*.h
/usr/include/linux/types.h:typedef __kernel_ptrdiff_t   ptrdiff_t;
/usr/include/asm/posix_types.h:typedef int              __kernel_ptrdiff_t;
sembra che ptrdiff_t sia definito come un int (32 bit).
Ciao ciao,


 hai scritto un'assegnazione.
Oopsss!!! Mi era sfuggito. Ovviamente è un errore di sintassi.
EMG

 a elementi di uno stesso vettore e' un intero (con segno).
Infatti. Non è necessario.
EMG

 
Ed invece ... ho sbagliato ...... era un if .. ma tanto il senso della
domanda lo avete capito benisimo !!!
Saluti (e Grazie ).
Antonio.

semplice if. Ma forse l'amico Piocco intendeva proprio un loop.
Hai perfettamente ragione, mi scuso di avere risposto proprio
distrattamente a questa domanda (non notando l'errore di '='
invece di '==' _E_ non notando la presenza di 'if' invece di
'while')!
Alex

sembra che ptrdiff_t sia definito come un int (32 bit).
Si`, sull'x86 non avrebbe molto senso definirlo altrimenti.
Su una macchina a 64 bit, invece, puo` avere senso
avere int di 64 bit, long e puntatori di 64. E` difendibile
anche una scelta diversa, ma qualche problema c'e`:
se char e` 8 bit, e int e` 64 bit, ho un solo tipo di
dimensione intermedia, short, e comunque lo voglia
definire non posso accedere da C standard a una
delle lunghezze che mi possono interessare, 16 e
32 bit; come fara` il mio compilatore a generare ad
esempio programmi che parlano in rete usando i
protocolli standard, che prevedono appunto campi di
lunghezza 8, 16, e 32 bit?
Per questo, mi aspetto che, in media, su una macchina
a 64 bit, si usera` char=1 byte, short=2, int=4, long=8.
Comunque, per completezza storica: sulle macchine a
16 bit, int era chiaramente 16 bit e long 32; i puntatori,
a seconda eventualmente del "modello di memoria",
potevano essere 16 bit, o 32.  ptrdiff_t, dunque, poteva
dover essere un long a seconda, appunto, del modello
di memoria (e similmente per size_t, se un dato modello
di memoria permetteva di avere in un singolo array piu`
di 64K byte, modello spesso detto "huge").
Il nuovo standard C "in cottura" prevede altri modi
(sin troppi!-) di specificare la lunghezza in bit di un
dato valore ("almeno tot", "non piu` di tot", "proprio
tot ne` piu` ne` meno", ecc, per vari valori di "tot").
Presumibilmente per prepararsi a eventuali future
macchine a _128_ bit...?-)
Alex

 potevano essere 16 bit, o 32.
Se proprio volessimo completare l'excursus storico, aggiungerei che
sulle macchine a 8 bit anche i long erano a 16 bit e cosě pure i
puntatori.
EMG

 puntatori.
Mi permetto di dissentire.  Anche nel K&R C un long garantiva almeno
32 bits.
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

32 bits.
Ma c'e` mai stato un compilatore C per sistemi a 8 bit che
rispettasse gli standard (veri o di fatto)?  Ricordo vagamente
un compilatore C per Commodore64, ma non quanto fedele
fosse al linguaggio "vero".
Alex

 32 bits.
Ma quando mai. Il K&R garantiva solamente che short <= int <= long. E
comunque io ho ancora un compilatore C per il Sinclair ZX Spectrum che
ha i long a 16 bit. Assieme ai tipi ad 8 bit, quella era la dimensione
pių adatta ad essere contenuta nei due tipi di registri disponibili su
quelle macchine.
EMG

 rispettasse gli standard (veri o di fatto)?
Questo non lo so. Quello che ho io (HiSoft C Compiler per il Sinclair ZX
Spectrum) non aveva neanche i float... :-(
EMG

 EMG
Mi spiace, ma hai torto.  Il K&R1 e' in Dipartimento, qui ho solo il
2: puoi guardare a pagina 18, se vuoi.  Un long e' almeno di 32 bits.
E lo era anche in K&R1.  Il tuo compilatore non era compliant.  Punto.


 Il tuo compilatore non era compliant.
Di questo ne ero perfettamente cosciente. Pensa che non aveva neanche i
float...
EMG