Newsgroup: it.comp.lang.c
Titolo: divisione per zero

ciao,
ho un dubbio relativo alla divisione per zero.
perchè quando compilo il seguente programma:
/* inizio */
int main(void) {
	int a = 2, b = -3;
	int x;
	x = a % (3 + b);
 
	return 0;
}
/* fine */
non mi da il warning relativo al tentativo di divisione per zero? 
pensavo che il compilatore espandesse automaticamente le espressioni 
costanti durante la compilazione...
se invece al posto di (3 + b) metto (3 - 3) allora correttamente ottengo:
divisionezero.c:6: warning: division by zero
os: gentoo linux
compilatore: gcc 3.4.4
parametri: -x c -ansi -pedantic -Wall -Wextra
grazie.

costanti durante la compilazione...
In questo caso non hai espressioni costanti, ma un valore assegnato a
una variabile. 

Andrea Laforgia ha scritto:

dunque io avevo capito che se si ha un'espressione costante del tipo 
(32252 * 7869) / 67003, il compilatore provvede a sostituirla con il 
risultato (cioè 3787) già durante la compilazione, in modo tale da 
rendere più efficiente la fase di esecuzione del programma. da quanto ho 
capito, inoltre, la stessa cosa avviene con (a*b)/c quando a=32252, b 
=7869 e c=67003.
tornando al programma iniziale, il compilatore dovrebbe capire che a % 
(3+b) vale 2 % (3-3) cioè 2 % 0, e quindi dare errore (durante la 
compilazione).
se non è così allora qualcosa mi sfugge...

ah forse ho capito.
#include <stdio.h>
int main(void) {
	int a, x;
	scanf("%d", &a);
	x = 2 % ( 3 - a );
	return 0;
}
ovviamente il compilatore non può prevedere il valore dell'espressione 
(3-a), che varrà 0 solo quando l'utente inserisce 3. in questo senso non 
si tratta di un'espressione costante.
leggendo adesso dal libro, vedo anche che il carattere 3 e il carattere 
a sono considerati due token di tipo diverso, il primo una costante e il 
secondo un identificatore. con tutta probabilità quindi un'espressione 
costante è un'espressione che contiene solo token costanti e non token 
identificatori, oltre ovviamente agli operatori e ai segni di interpunzione.

compilazione).
Quello che il compilatore solleva è, semmai, un warning, non un errore
(sei libero di fare tutte le divisioni per zero che vuoi).  Il motivo
per cui questo non succede è che non si ha a che fare con costanti, ma
con variabili.

costante è un'espressione che contiene solo token costanti
Un'espressione costante è un "literal" o una operazione tra "literal".

 coinvolgerebbe l'ottimizzatore in predizioni troppo complesse.
Mi intrometto nella discussione per porre una domanda, venutami in mente
per curiosità, sicuro che qualcuno saprà rispondermi, voglia permettendo
;). Fino a che punto una predizione del genere sarebbe 'complessa'? Mi
spiego meglio con un esempio.
Il compilatore del Borland C, se impostato correttamente, al momento di
compilare qualcosa come
#include <stdio.h>
int main(int argc, char **argv)
{
 	int a=0,b;
 	printf("%d %d", a,b);
 	return 0;
}
genera un warning alla riga della printf perché le si sta passando un
parametro possibilmente non inizializzato (b). Non sono riuscito a
generare lo stesso warning con il gcc, non so se perchè l'opzione che ho
scelto (-Wall) non è abbastanza severa o perchè magari questa
possibilità non è prevista affatto. :)
Comunque, dato che un compilatore riesce a tenere traccia di queste
non-inizializzazioni, sarebbe troppo gravoso (in termini di memoria
occupata durante la compilazione, o difficoltà di progetto, o
quant'altro) fare in modo che esso si accorga anche di situazioni come
quella presentata da fctk?
Ciao a tutti
Dark_Knight
-- 
The Lord Of The (Token) Ring
  (the fellowship of the packet)
"One Ring to link them all, One Ring to ping them,
one Ring to bring them all and in the darkness sniff them."

 quella presentata da fctk?
Varia molto da compilatore a compilatore probabilmente.  In ogni caso 
anche il gcc da` un warning, ma solo se c'e` l'ottimizzazione.
$ cc -O2 -pipe -Wall -march=i486 tst.c -o tst
GNU C version 3.4.5 (i486-slackware-linux)
         compiled by GNU C version 3.4.5.
tst.c: In function `main':
tst.c:4: warning: 'b' might be used uninitialized in this function
Addirittura il gcc (ma molti altri compilatori) elimina il codice che 
prevede non potra` mai essere eseguito se compili con le ottimizzazioni.
#include <stdio.h>
int main(int argc, char **argv)
{
   int a = 0, b;
   printf("%d %d", a, b);
   if (a == 1) {
         printf("Codice non generato");
   }
   return 0;
}
Per gli statements [ if (a == 1) printf("Codice non generato"); ]
non viene generato codice nell'eseguibile, potendo valutare che la 
variabile 'a' al momento del test e` sicuramente 0.
In genere non importa quante istruzioni ci possono essere in mezzo, ma 
penso che il processo di ottimizzazione valuti se la variabile e` 
soggetta ad altre manipolazioni prima di essere valutata (come nel caso 
della variabile 'a' nell'esempio) oppure ad altre inizializzazioni 
(variabile 'b').


 > perchč quando compilo il seguente programma:


 
In questo caso il compilatore riesce a capire anche in fase di 
compilazione che vi e' una divisione per zero.  Pero` non garantisco che 
nel primo caso (const int b = -3;) sia vero per tutti i compilatori.
