Newsgroup: it.comp.lang.c
Titolo: Un Warning incomprensibile

Uso Win7 64bit e sto facendo delle prove con Code::Blocks + MinGW.
In una subroutine ho la seguente istruzione:
 
if(n < 0) n = -n;
 
e il compilatore mi segnala:
 
warning: will never be executed|
 
Non riesco a capire a cosa è dovuta questa segnalazione.
In effetti però il codice viene eseguito correttamente come posso
verificare controllando la variabile prima e dopo la riga.
Anche altre varianti che hanno lo stesso effetto nel codice come
 
if(n < 0) n = 0 - n;
if(n < 0) n -= 2*n;
if(n < 0) n = (-1) * n;
 
danno la medesima segnalazione.
Invece
 
if(n < 0) abs(n);
 
non provoca alcuna segnalazione come anche
 
if(n < 0)
{
  a = 1;
  n = -n;
}
 
Altri compilatori (LCC-Win32, Borland 5.5) non danno alcuna
segnalazione.
Qualcuno mi sa dare una spiegazione?
Grazie.
 
-- 
Dano

 Qualcuno mi sa dare una spiegazione?
 
Qual è il tipo di n?

 Qualcuno mi sa dare una spiegazione?
 
I compilatori possono emettere qualsiasi tipo di warning essi credano, 
senza per questo andare in conflitto con lo standard ANSI.  E' 
normalmente, quindi, attendersi diversi warning su diversi compilatori.
In alcuni di essi è possibile configurare (abilitando e disabilitando) 
i warning da emettere (chiamate a funzioni senza dichiarazione, 
variabili static non usate, ecc)
 
Ed è proprio questo che è praticamente impossibile scrivere codice di 
un'applicazione relativamente complessa che non genera alcun messaggio 
di warning in fase di compilazione (a meno di non avere un compilatore 
che può spegnere qualsiasi tipo di warning...)
 
Naturalmente ciò *non* vuol dire che i warning debbano essere ignorati, 
perchè nella maggior parte dei casi rappresentano un errore reale o di 
concetto del codice.
 
Nel tuo caso, molto probabilmente n è di tipo unsigned e quindi è 
intrinsecamente *non negativo*.  Il test che fai (n < 0) non avrebbe 
senso, perchè sarebbe *sempre* vero.
 

senso, perchè sarebbe *sempre* vero.
 
No, n è di tipo int.
Anche a me era venuto lo stesso dubbio e ho provato anche a
specificare "signed int", ma non cambia niente.
Da notare che l'istruzione 
 
if(n < 0) a = 1;
 
non da nessuna segnalazione, Quindi il warning compare solo se si usa
la stessa variabile nel test e nell'assegnazione.
 
Se volete provare vi posto anche il codice completo di esempio
 
 
/*------------ Codice ---------------*/
#include <stdio.h>
#include <stdlib.h>
 
int seconda(int);
 
int main(void)
{
  int x;
 
  x = seconda( 100);
  printf("%d\n", x);
 
  x = seconda(-100);
  printf("%d\n", x);
 
  return(0);
}
 
int seconda(int n)
{
  int a = 0;
 
  printf("%d -> ", n);
  if(n < 0) a = 1;
  if(n < 0) n = -n;
  printf("%d -> ", n);
 
  return((a)? n :- n);
}
 
-- 
Ciao, Dano

Qual è il tipo di n?
 
E' di tipo int
Vedi anche quanto ho risposto a pozz
 
-- 
Ciao, Dano


 > [...]
 
A me, Code::Blocks+MinGw (4.4.1), non da nessun warning.
 
 

 In Sun, 18 Mar 2012 09:38:09 +0100, pozz 

Sei sicuro che il warning sia giusto ma che sbagli la riga indicandoti quella successiva? :-/
Ciao!

 [...]
 
 
Ciao  Manlio

seconda con il literal 100, ottieni ancora il warning?
 
Si, purtroppo non cambia niente.
 
-- 
Dano

A me, Code::Blocks+MinGw (4.4.1), non da nessun warning.
 
Anche io: Code::Blocks 10.05 e MinGW 4.4.1 installato da 10 giorni per
la prima volta e stavo facendo delle prove.
 
Hai attivato su Code::Blocks il warning 
 
Warn if the compiler detects that code will never be executed
[-Wunreachable-code]
 
perché il solo -Wall non basta per vedere la segnalazione.
 
-- 
Ciao, Dano

Sei sicuro che il warning sia giusto ma che sbagli la riga indicandoti quella successiva? :-/
 
Ne sono piuttosto sicuro: il warning compare anche se sposto la riga
in una diversa posizione (ad esempio all'inizio della funzione),
compare anche se la metto nel main, invece scompare se la cancello o
la sostituisco con la equivalente 
 
n = abs(n);
 
e scomapre se accorpo i due if in uno soltanto.
 
if(n < 0)
{
  a = 1;
  n = -n;
}
 
Non compare nemmeno se scrivo il test nel modo seguente:
 
if(n < 0) n = -2*n/2;
 
che chiaramente è la stessa cosa.
 
E senz'altro giusto che la segnalazione arrivi quando scrivo
 
if(n < 0) n = n;
 
Questa istruzione non fa niente, il compilatore se ne accorge e non
genera codice per questo. Credo che, in parte, confonda 
 
n = -n 
 
con 
 
n = n 
 
e, pur generando correttamente il codice, segnala il warning.
Se l'istruzione é appena più mascherata come nel caso di
 
n = -2*n/2
 
gli sta tutto bene.
 
-- 
Dano
 


mingw32-gcc.exe -Wunreachable-code -pedantic -Wextra -Wall  -O2 
-I..\prova -Iparam  -c "C:\Users\Giuseppe\Documents\Temp\CodeBlocks 
Projects\tmp\main.c" -o "C:\Users\Giuseppe\Documents\Temp\CodeBlocks 
Projects\prova\.objs\main.o"
 
mingw32-gcc.exe  -o prova.exe 
"C:\Users\Giuseppe\Documents\Temp\CodeBlocks 
Projects\prova\.objs\main.o"   -s
 
Output size is 6.50 KB
Process terminated with status 0 (0 minutes, 0 seconds)
0 errors, 0 warnings
 
 


 
Ho trovato da cosa dipende: le opzioni di ottimizzazione.
 
Se uso -O, -O1 oppure -O3 mi compare il warning
se invece uso -O2 (come hai fatti tu) tutto ok.
 
Già, ma perché? Quali sono le opzioni più opportune da utilizzare?
 
-- 
Dano

 Quali sono le opzioni più opportune da utilizzare?
 
In passato ricordo che O3 ha sempre avuto qualche problemino
quindi mi e' sempre stato sconsigliato. Usando O2 non ho mai
avuto problemi. Giro lo stesso consiglio anche a te! :)
 
ciao
Giacomo
 

avuto problemi. Giro lo stesso consiglio anche a te! :)
 
Perfetto. Impostato su Code::Blocks
Ciao, e grazie
 
-- 
Dano

 di warning in fase di compilazione (a meno di non avere un compilatore
 
stai scherzando vero?
 
Ciao Jack

 viene riordinato in modo errato generando codice unreachable.
 
questa e' una tua supposizione, poterbbe essere anche il contrario,
cioe' l'algortimo che genera il warning che 'e buggato quando ha a che
fare con certe ottimizzazioni (che probabilmente non capisce).
 
Ciao Jack


Certo che e' una supposizione! Mica ho la sfera di cristallo! :)
 
ciao
Giacomo


No, per niente.  Il compilatore può emettere qualsiasi messaggio egli 
ritenga opportuno, quindi è impossibile essere sicuri di generare codice 
warning-free per qualsiasi tipo di compilatore.
 
Naturalmente i warning sono per la maggior parte indice di un problema, 
risolvendo il quale si evita il warning.  Ed è quindi desiderabile 
eliminare la maggior parte dei warning.
 
Ma non sempre è così, non sempre un warning è effettivamente un errore e 
quindi non sempre riesci ad eliminarli tutti.
 
Poi dipende da quanto è configurabile un compilatore.  Ce ne sono alcuni 
che si ostinano ad emettere warning inutili e non hanno opzioni per 
nasconderli, a meno di non filtrarli a posteriori con un altro 
programma.  E non puoi neanche accusare il fornitore del compilatore di 
non essere standard ANSI solo perchè emette warning inutili!

 fare con certe ottimizzazioni (che probabilmente non capisce).
 
Mi *aspetto* che il codice che individua la reachability del codice
passi (almeno anche) dopo il codice che ottimizza, visto che un botto di
ottimizzazioni cambiano proprio la reachability.
 
-- 
-riko
http://www.enrico-franchi.org/
 
http://rik0-techtemple.blogspot.com/
 

 > On 18 Mar, 09:38, pozz

Sono parzialmente d'accordo. Il primo esempio che mi viene in mente è il compilatore MS che permette uno switch per compilare ANSI C in modalità strict, ma visto che gli include interni contengono commenti "//" è praticamente impossibile compilare in quel modo a meno di disabilitare lo specifico warning intorno alle inclusioni. Inutile dire che IMHO è un enorme porcata :D
 
Detto questo con il gcc invece devo dire che non mi viene in mente un caso in cui mi sia capitato un i warning "non vero"..
 
Per quanto riguarda la compilazione con -O3 invece ricordo chiaramente casi in cui gli eseguibili *non funzionavano*, uno tra tutti (se la memoria non mi fa scherzi) il KDE (se lo ricorderanno i gentoo-isti presenti, che dovevano cambiare le CFLAGS per la compilazione di solo quel pacchetto!).
 
Ciao!

 caso in cui mi sia capitato un i warning "non vero"..
 
Non esiste mica il compilatore MS e il compilatore gcc...
 
Non sono un esperto, ma il gcc viene usato per compilare linux e durante 
la compilazione mi sembra di aver visto una caterva di warning.


Se per "compilare linux" intendi il kernel linux allora sì, ma è anche ovvio: essendo il kernel un software di basso livello e il C un linguaggio ideato per il livello utente è necessario forzarlo di quando in quando per adattarlo allo scopo (per dirne una, il packing delle strutture non è ANSIC, ma nei protocolli hardware il padding non ce lo puoi mettere!); oltretutto il kernel linux fa un uso spropositato dei builtin del gcc (likely, nessuno? ;)) che lo rende *non compilabile* con qualsiasi altro compilatore.
 
Se per "compilare linux" invece intendi tutto il software (GNU, ad esempio) che di solito si trova in ogni distribuzione, dipende: ci sono codici che compilano senza warning GNU (eh sì, è uno standard che ha i suoi warning), altri senza warning ANSI, altri che dipendono dai settaggi del compilatore che specifica l'utente che compila, altri non compilano proprio perché l'autore non ha aggiornato bene il suo repository. E' un mondo variegato (fortunatamente!)
 
Ciao!