Newsgroup: it.comp.lang.c++
Titolo: c/c++ standard

Ciao a tutti nel ng.
Ho notato che c'è una differenza tra il compilatore gnu C++  (g++) e 
visual studio .net 2003 compilando per win32.
Il seguente codice,
 int main()
{
    int size;
    cout<<"\nSize?: ";
    cin>>size;
    int buffer[ size];      //questa è la linea incriminata.
    cout<<"\nBuffer created, size: "<<size <endl;
    return 0;
}
Funziona con g++  ma con VS.net ottengo:
std.cpp(6): error C2057: expected constant expression
std.cpp(6): error C2466: cannot allocate an array of constant size 0
std.cpp(6): error C2133: 'buffer' : unknown size
------------------------------------------------------------------------------------------
Cosa dice ANSI/ISO C++?	
Ciao e grazie per un eventuale chiarimento.

 
secondo me non dovrebbe funzionare
-- 
Pela

>    int buffer[ size];      //questa è la linea incriminata.


 
Lo Standard dice che quel codice non è valido. 
Quel costrutto (introdotto dallo standard del C99 con il nome di VLA,
Variable-Length Array) è implementato dal GCC come estensione non standard,
ma non è previsto dalla sintassi del C++ .
Max


--  
Postato da Virgilio Newsgroup: scopri i nuovi gruppi 
Eros, foto e video a 
http://newsgroup.eros.virgilio.it

    int buffer[ size];      //questa č la linea incriminata.
Non dovrebbe funzionare in c++. In c99 e' prevista una cosa simile, ma 
non mi sembra che lo sia in c++. Se vuoi avere un array la cui 
dimensione e' nota solo a runtime, devi usare new. Comunque questo e' 
solo il metodo piu' semplice, ne esistono altri.
int *buffer;
...
buffer=new int[size];
Qualcuno sa come disattivare il supporto per quella funzionalita'? Ho 
provato a compilare con -ansi o -std=c++98 ma continua a funzionare 
senza nemmeno un warning.
-- 
Devaraja (Xdevaraja87^gmail^c0mX)
Linux Registerd User #338167
http://counter.li.org

 visual studio .net 2003 compilando per win32.
int main()
{
    int size = 42;
    /* ... */
    int vettore[size];
}
č codice NON valido in C++ e in C89 (standard C originale, del 1989)
č invece valido in C99 (standard C attuale, revisione del 1999)
In pratica, se stavi compilando come C++, ha ragione il Visual Studio
D'altra parte, se col G++ ci metti un --pedantic --ansi tra le opzioni, sono
convinto che ti segnali l'errore anche li.
-- 
Gerolamo 

 
Ecco, era quella l'opzione che mi serviva.


 non mi sembra che lo sia in c++. 
trovo la cosa comodissima benché non standard, A PATTO però di 
accertare come il compilatore la gestisce.
Mi spiego, sicuramente lo stack è memoria dinamica non diversa 
concettualmente (in senso hardware, non di scope e lifetime 
ovviamente) dallo heap, ma solitamente è molto diversa come 
quantità totale disponibile (intendo che lo stack è una risorsa 
normalmente meno ampia dello heap). Inoltre un buon codice che 
usa esplicitamente new può prendere contromisure in caso di 
fallimento, uno stack overflow lascia indifesi in ogni senso.
Chiedo quindi se qualcuno sa se, nell'implementazione della 
sintassi più avanzata C99, venga inserito codice ombra per il 
controllo a runtime dello stack overflow (nel senso di prendere 
numericamente atto dello stack libero residuo e del valore del 
numero di byte richiesti, e compararli, in modo che il programma 
crashi in modo regolare e tempestivo e non tiri avanti con 
l'array sovrapposto a chissà cos'altro) e non soltanto una 
specie di
SUB ESP, WORD PTR [EAX]
dove EAX è l'indirizzo della variabile con le dimensioni dell'array
o qualcosa di altrettanto inconsapevole e automatico.
Grazie per eventuali precisazioni (se qualche volenteroso avesse 
il GCC e un debugger potrebbe simulare uno stack crash in tempo 
reale, dimensionando un'array fisso sullo stack quasi al pelo 
della capienza massima ed uno dinamico di dimensioni variabili 
per vedere che succede quando si esaurisce lo stack.
cia
Soviet_MArio


 Ecco, era quella l'opzione che mi serviva.
Credo tuttavia che quando si compila un sorgente C++ sarebbe piu'
opportuno se g++ di default non accettasse i VLAs a meno che non venga
settata una opzione tipo --vla (praticamente il contrario di come e'
ora).
Tommaso
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 trovo la cosa comodissima benché non standard, 
il problema e' che una cosa puo' anche essere comodissima ma se non e'
standard non conviene in genere usarla in quanto rende il codice meno
portabile.
noi ad esempio abbiamo un codice che deve compilare su diverse
piattaforme, alcune basate su gcc, altre su vc++.net altre su diab,
etc..


 
Con una breve ricerca, penso che il problema sia questo:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15508
Vedi anche commenti #13, #14.
Commento #8: sembra sistemato in GCC > 3.5.
Saluti,
-- 
Matteo Settenvini
FSF Associated Member
Email : 
mat...@member.fsf.org
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d--(-) s+:- a-- C++ UL+++
P?>++ L+++>$ E+>+++ W+++ N++ o?
w--- O- M++ PS++ PE- Y+>++
PGP+++ t+ 5 X- R tv-- b+++ DI+
D++ G++ e h+ r-- y?
------END GEEK CODE BLOCK------

Soviet_Mario ha scritto:

Argomento interessante.. adesso faccio qualche prova, ma credo che gcc 
non si preoccupi molto di queste cose, infatti e' anche possibile avere 
un VLA a lunghezza negativa...
Comunque questa e' la prova (se intendevi altro fammi sapere):
--a.c--
#include <stdio.h>
int main()
{
   int dim;
   scanf("%d",&dim);
   int ar1[16];
   int ar2[dim];
   return 0;
}
--------
'$gcc a.c -std=c99 -Wall --pedantic' (2 warning per le var non usate)
'$gdb a.out'
'(gdb) disassemble main'
Output di gdb:
...
...
sub   $0x64,%esp        (alloca il primo array)
and   $0xfffffff0,%esp  (arrotonda esp a 16)
...
...
chiamata a scanf e spostamento del num letto su eax
dec   %eax          (decrementa il num di 1)
shl   $0x2,%eax     (eax<<=2)
add   $0x4,%eax     (eax+=4)
add   $0xf,%eax     (eax+=16)
shr   $0x4,%eax     (eax>>=4)
shl   $0x4,%eax     (eax<<=4)
sub   %eax,%esp     (alloca il VLA)
Quindi se inserisco 10 (1010 in binario)
00000000 00001010
00000000 00101000
00000000 00101100
00000000 00111100
00000000 00000011
00000000 00110000
diventa 48 che e' il multiplo di 16 piu' piccolo che puo' contenere 40 
(10 int). Quel 16 e' l'allineamento di default del mio stack. Alla fine 
insomma sembra solo che gcc si limiti ad arrotondare il numero e a fare 
l'allocazione dei VLA dopo gli array normali. Non ho avuto tempo di 
provare uno stack overflow, poi vedo.
Sicuramente sbaglio qualcosa perche' se anche passo 400000000000 come 
argomento non succede niente, pero' e' probabile che mi stia 
dimenticando qualche cosa perche' ho studiato tutto il giorno e sono 
fuso. Se ci sono errori fatemi sapere.


 ora).
Credo che sia per retrocompatibilità. Codice del genere lo ho visto da 
anni (anche e soprattutto in C, ma ben prima che ci fosse un supporto 
seppur sbocconcellato a C99). Da un punto di vista teorico sono 
d'accordo.
Esattamente come sarei più contento se il linker di default su Linux 
evitasse di ingoiare qualunque schifezza, lasciando poi a me il compito 
di mettere a posto le cose (scritte da altri) quando devono girare su 
sistemi di estrazione BSD (per esempio il linker di MacOS X).
Tuttavia sarebbe davvero bello che venisse introdotto nello standard 
anche C++. Complessivamente credo sia molto comodo (specie se si usa 
spesso codice matriciale -- e a me capita --). In C++ allocare una 
matrice "contigua" non è affatto un problema, ma sicuramente ci si mette 
più tempo che a scrivere mat[x][y] :)
Tornando al "problema" in se, GNU ha scelto di usare di default la 
"modalità" GNU, quindi tutte le estensioni (beh, non tutte) abilitate.
-riko

 fallimento, uno stack overflow lascia indifesi in ogni senso.
Di solito per stack overflow si intende un'altra cosa rispetto a quella 
che dici tu.
Ad ogni buon conto, considera che un vla è una variabile automatica a 
tutti gli effetti. Quindi può essere usato per RAII, per dire.
E a livello più basso, è molto più veloce da usare perchè non dipende da 
una chiamata di sistema (come invece fa new). Certo, se poi il codice fa 
altre chiamate di sistema, il vantaggio sostanzialmente sparisce.
-riko

 
Cosa significa RAII?


 una chiamata di sistema (come invece fa new). 
altrochè, infatti ! considera anche la sostanziale possibilità 
di ottimizzazioni nell'uso dei registri per indirizzare oggetti 
relativamente allo stack
cmq da quanto ho letto della volenterosa prova di DevarajA, che 
RINGRAZIO, in effetti non pare esserci alcun codice di controllo 
che verifichi la dimensione, la qual cosa rende il costrutto 
piuttosto rischioso già in casi prevedibili, e troppo pericoloso 
in situazioni in cui la dimensione viene partorita da lettura di 
files, input utente, calcoli complessi etc. Nulla vieta il 
programmatore di vagliarla lui .... ma esiste nello standard una 
funzione che ritorna la quantit di byte disponibili sullo stack 
in un dato momento ? Se non esiste, non ci sono difese .... e 
anche tale analisi a mano non serve se non in modo aleatorio.
ciao
Soviet_Mario


> -riko


 Cosa significa RAII?
Resource acquisition is initialisation.


 che dici tu.
void f(){f();}
int main(){f();}
Compiling...
main.cpp
warning C4717: 'f' : recursive on all control paths, function will cause
runtime stack overflow


 spesso codice matriciale -- e a me capita --).
beh... per la maggior parte dei casi hai l'alternativa di usare std::vector
Penso che sia per questo che non è stata introdotta questa estenzione nel 
c++
-- 
Gerolamo 

 std::vector
Oppure dare un'occhiata alla classe std::valarray, che AFAIK è stata
progettata espressamente con lo scopo di intervenire in questi casi
(accoppiata, ad esempio, con la classe std::slice_array).
HTH.
-- 
[ Andrea Spadaccini - a.k.a. Lupino/Lupin85 - Catania - ICQ#: 91528290 ]
[ GPG ID: 5D41ABF0 - key @ 
pgp.mit.edu
 - Slackware 10.1 w/Linux 2.4.22 ]
[ Linux User # 313388 - MAIL: a.spadaccini(at)catania(dot)linux(dot)it ]

 cosa rispetto a quella che dici tu.
Scusa, di solito cosa si intende secondo te!?
I casi sono due, o ho frainteso te o soviet_mario.


 C99, evidentemente qualcheduno ha valutato il rischio come limitato.
Sinceramente non vedo come la cosa possa dare più problemi di altre
features del tutto accettate. Voglio dire, per allocare più memoria di
quanta disponibile (e fare volare tutto via in un  turbine di bad_alloc)
non ci vuole molto.
Poi che bad_alloc si possa anche catchare ok... ma generalmente si può
essere messi parecchio male comunque quando si arriva a quello stato...
-- 
non vincono, non vinceranno, non hanno domani
la forza è nel puntello impugnato da oneste fortissime mani

 beh... per la maggior parte dei casi hai l'alternativa di usare std::vector
Chiaro, ma purtroppo non sempre un vector è applicabile o vantaggioso.
Diciamo che con le duemila features del C++ non considererei "rovinata"
la filosofia se ci fosse anche la mille e più un-esima.


 cosa significa la sigla ?
Ti faccio un esempio pratico. Il codice sottostante usa delle chiamate
di sistema posix per aprire i files e per fare del locking. Ci sono due
implementazioni giocattolo (non sono testate e probabilmente sono
buggate, le ho scritte in 5 minuti) di classi C++ che mascherano il
concetto di filedescriptor (avrei usato gli ofstream, se avessi trovato
un modo portabile per ottenere i descrittori di files).
Ecco, nella funzione "do_critical" ogni tanto vengono lanciate
eccezioni, ognitanto si termina normalmente, ma in ogni caso, senza
sforzo e senza codice aggiuntivo i wrapper C++ usano il fatto di essere
variabili automatiche per gestire correttamente le risorse.
Invece di usare funzioni posix fuori standard, avrei potuto chiamare
funzioni fittizie, oppure cavarmela con dei commenti (e forse avrei
fatto meglio, visto che sospetto bachi in ogni armadio di quel codice).
Comunque un minimo funziona per capire...
============================ easylock.cc =============================
#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <exception>
#include <cstdlib>
#include <cstring>
#include <cerrno>
extern "C" {
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/uio.h>
}
class Lock{
    const int fd_;
    public:
    Lock(int fd) : fd_(fd) {
        int olderrno = errno;
            int res = flock(fd_, LOCK_EX);
            if (res<0){
                perror(NULL);
                throw "Cannot lock!";
            }  
            errno = olderrno;
            std::cout <<"Locked"<< std::endl;
        }
 
        ~Lock(){
            flock(fd_, LOCK_UN);
            std::cout <<"Unlocked"<< std::endl;
        }
};
class OldFile{
    int fd_;
    public:
    OldFile(const char* fname){
        int olderrno = errno;
        fd_ = open(fname, O_APPEND|O_WRONLY|O_CREAT, 0755);
        if (fd_<0){
            perror(NULL);
            errno = olderrno;
            throw "Unable to open file!";
        } else {
            errno = olderrno;
            std::cout <<"Opened"<< std::endl;
        }
    }
 
    int get_fd(){ return fd_; }
 
    ssize_t write(const char* s){
        std::cout << s << std::endl;
        std::cout << strlen(s) << std::endl;
        return ::write(fd_, s, strlen(s) );
    }
 
    ~OldFile(){
        std::cout <<"Closed"<< std::endl;
        close(fd_);
    }
};
void do_critical(const char* fname){
    static int counter=0;
    OldFile of(fname);
    Lock lock(of.get_fd());
    //do something
    of.write("// append...\n");
    if (counter%2){
        throw std::exception();
    }
    ++counter;
}
int main(){
    for(int i=0; i < 5; ++i){
        try{
            do_critical("easylock.cc");
        } catch (std::exception &e){
            std::cout << "Caught!" << std::endl;
        }
    }
    return 0;
}
============================== end =================================
Lo stesso discorso si può applicarlo a socket, "databases", aree di
memoria...


 dall'utente.
di solito un array (di interi, di double o altri tipi base) è 
acceduto uno alla volta, usando registri indice. Se esso è sullo 
stack richiede istruzioni più brevi, perché non ci sono 
indirizzi da caricare da memoria. Cmq questa è una ipotesi, 
dipende in toto dall'implementazione.
ciao
Soviet_Mario


 Scusa, di solito cosa si intende secondo te!?
Semplicemente ho risposto a una cosa pensando ad un'altra :)
-- 
non vincono, non vinceranno, non hanno domani
la forza č nel puntello impugnato da oneste fortissime mani

 
Un po' OT, ma credo che esista la funzione di gcc -fstack-protector (c'è
qualcosa anche per msvcpp), che aiuta a fare quanto dici.
Per la cronaca, invece: facendo un programma oggi sono andato a fare
proprio il danno in discussione: troppe chiamate ricorsive alla stessa
funzione fino a che non sono andato a sforare nello stack e il programma
è terminato con un bel sigsegv (due distruttori mutuamente ricorsivi
causa "ciclo nel grafo", guardando ai puntatori). Ed erano solo ~1500
righe di codice... :ashamed:
Solo a significare che effettivamente bisogna stare attenti, o ci si
rompe la testa un pezzo sul perché una chiamata alle STL riesca ad
andare in sigsegv. ;-)
Ciao,


 
Ma non c'era "valarray"? (domanda non retorica)


 Ma non c'era "valarray"? (domanda non retorica)
si, ma valarray non e' sicuramente una delle cose migliori del C++, e
poi servirebbe per cose diverse, per fare processing di array di valori
numerici.
Ecco un esempio trivial:
#include<iostream>
#include<valarray>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
   srand(time(0));
 
   int number_of_elements = rand()%15 + 1;   
   valarray<int> va(number_of_elements); 
   for(int i=0;i<number_of_elements;++i)
      va[i] = rand()%100;   
   cout << "Creato valarray<int> va con " 
        << number_of_elements << " interi "
        << "random" << endl; 
   for(int i=0;i<number_of_elements;++i)
      cout << va[i] << endl;
 
   va *= 3;
   cout << "Moltiplicato ogni elemento per 3" << endl;
   for(int i=0;i<number_of_elements;++i)
      cout << va[i] << endl;      
}
nota come va *= 3 moltiplichi ogni elemento dell'array per 3.
se non vuole lavorare con array di valori numerici allora meglio usare
vector:
srand(time(0));
int number_of_elements = rand()%15 + 1;   
vector<int> v(number_of_elements); 
cout << "vector di " << v.size() 
     << " elementi" << endl;
che ovviamente anche esso e' capace di prendere la dimensione
at-run-time (e cosa che i VLAs non possono fare, vector puo' anche
cambiare di dimensione).
Il discorso e' che ovviamente i VLAs sono piu' leggeri e lavorano sullo
stack mentre con vector v e' sullo stack ma gli elementi di v sono sullo
heap:
vector<int> v(100000);
Per concludere ammetto che, per cio che riguarda il C, visto che lavoro
con il C++, sono rimasto al C89 e di VLAs e C99 in generale so poco.


 heap:
Esatto. Inoltre un vector di vector a meno di smacchinare con gli
allocatori non ha memoria allocata contigua (o meglio, ciascun vector la
ha, ma poi le aree di memoria non necessariamente lo sono).
Inoltre sono relativametne "complessi" e certi tipi di ottimizzazione
imho non vengono fatte, cosa che invece sarebbero possibili con i più
stupidi vlas.


 tutti gli effetti. Quindi può essere usato per RAII, per dire.
Potrebbe se la prossima versione del C++ aderisse alle scelte fatte in
C99, ma ora come ora non è così e sospetto che se adesione ci sarà,
sarà limitata ai soli tipi previsti da C99:
 
http://www.research.att.com/~bs/examples_short.pdf
Barone Frankenstein
-- 
There is no place like /home.

 sarà limitata ai soli tipi previsti da C99
Anche perchè ripensandoci mi viene in mente che sarebbe quasi inutile
per RAII, visto che al costruttore degli oggetti non possono essere
passate variabili, quindi funziona solo se essendo Type la classe, può
essere chiamato Type() [ questa è l'implementazione del gcc, per lo
meno, quindi si a chi ha un costruttore senza parametri, o chi ha un
costruttore i cui parametri hanno tutti un default ].


 nota come va *= 3 moltiplichi ogni elemento dell'array per 3.
il thread si sta ottizzando sempre più, ma mi piacerebbe 
nuovamente un nuovo parere da qualcuno che conosca i compilatori 
attuali (detta così non vorrei far sembrare che io conosca 
quelli datati, non conosco manco quelli !).
La domanda è questa, e ancora riguarda l'implementazione interna :
valarray è semplicemente un involucro intorno a iterazioni 
scritte in normale linguaggio C o, secondo voi, si avvale delle 
istruzioni multidato avanzate dei moderni processori ?
Se è la seconda, a parte la non portabilità, è molto potente 
come feature per certi scopi (ad es. un tempo facevo ruotare dei 
solidi maneggiando matrici di coordinate che eseguivano miriadi 
coppie di moltiplicazioni per seni e coseni (precalcolati) e 
penso che codice simile schizzerebbe più veloce di molto 
accedendo alle istruzioni multiple data dei processori .... se è 
solo una shorthand che usa codice ordinario ... beh, allora che 
ciofeca sono sti valarray ? :-)
ciao e grazie dei commenti
CCCP++Mario


 ciao e grazie dei commenti
valarray ha buone prestazioni, ma non e' certamente la soluzione con
prestazioni migliori.
se vuoi qualche cosa con soluzioni molto buone forse e' il caso di
lasciare valarray da parte ed usare altro, ad esempio Blitz++ :
http://www.oonumerics.org/blitz/whatis.html
per cio' che riguarda le tue domande lo standard dice:
"the valarrayy components provide support for n-at-a-time processing,
potentially implemented as parallel operations on platforms that support
such processing."
In pratica la risposta e': "dipende dall'implementazione". Certamente
nelle implementazioni che ho io c'e' poco di parallelo.
Dai una occhiata a:
http://osl.iu.edu/~tveldhui/papers/DrDobbs2/drdobbs2.html
potrebbe interessarti, in particolare, "figure 2: DAXPY benchmark" che
va vedere sia Blitz++ che valarray che Fortran 77.
HTH,


 ciofeca sono sti valarray ? :-)
Guarda che spesso e volentieri è una leggenda che il codice scritto a
mano in assembly sia necessariamente più veloce di buon codice C o C++
in mano ad un buon compilatore ottimizzante.
Il funzionamento dei processori (lunghezza di pipeline, presenza o meno
di cache, ma soprattutto quanta etc) è molto variabile. Pensa che spesso
ottimizzando per le dimensioni si ottengono migliori prestazioni che
ottimizzando per la velocità. Perchè il fatto di ficcare tutto il
segmento di codice in cache rende comunque più veloce la faccenda che
fare altrimenti. Per dire... e qui si che si sta andando OT! :)


 generico processore di una data famiglia.
La peculiarita' di valarray e' che e' stato pensato per consentire
tecniche di ottimizzazione particolari. come la vettorizzazione per
multiprocessori e l'utilizzo di expression template per l'eliminazione
di valori temporanei (come fa Blitz++). Se non sbaglio libstdc++ usa
gli expression template, mentre l'unica implementazione "vettorizzata"
di cui ho sentito parlare e' quella di Glen Low
(
http://www.pixelglow.com/macstl/
).
Ciao,
Nicola

enrico franchi ha scritto:

sono d'accordo con te nel dire che spesso e volentieri è come dici.
Ma penso che anche tu concorderai che non è sempre 
necessariamente così. Dipende da quanto conosci i dettagli di un 
problema e quanto esso è specifico e vicino all'harware 
particolare. Le funzioni di libreria per quanto ottimizzate 
dovrebbero essere più general purpose e quindi avere un minimi 
di resilienza, di controlli in più. Ovviamente se 
l'implementazione supporta già da sé il calcolo parallelo (in 
senso reale, nativo, dell'hardware) non sussiste alcun bisogno 
di tentare di migliorare alcunche. Ma imho il peggior calcolo 
parallelo nativo scritto a mano in assembly pedestre è di sicuro 
parecchio più veloce del miglior codice sequenziale ottimizzato 
dal compilatore. A essere precisi dovrei dire che in realtà 
dipende dal volume di dati / istruzione da trattare. Se do in 
pasto un array di 100 elementi, il vantaggio potrebbe essere 
nullo o addirittura penalizzante. Se sono 10000 potrebbe essere 
apprezzabile. Se devo calcolare l'arcotangente iperbolica di una 
matrice di un megabyte, il codice parallelo annienta le 
prestazioni di quello che emula solo il parallelismo, comunque 
scritti siano i rispettivi.
riciao
P.S. mi viene il dubbio di avere sbagliato destinatario della 
risposta .... ma non riesco a ricostruire il flusso del 
discorso, ho un attimo di vuoto ... se qualcosa non torna, ho 
cannato io !
CCCP++Mario


 dal compilatore. 
Non capisco perchè proprio a mano in assembly. Io il (poco) calcolo 
parallelo che ho fatto, lo ho fatto con queste:
http://www.openmp.org/drupal/
Come vedi puoi anche usare il C++. Ah, e sbattere le cose su un cluster 
si che può essere veramente vantaggioso. A parte che immagino che 
possano essere usate anche in ambiente multiprocessore su una singola 
macchina. Da questo punto di vista che io sappia è trasparente.
Io poi le ho *usate* su un cluster già configurato. Non ho configurato 
nulla e la parte di amministrazione di sistema a me non è mai toccata.
-riko

 (
http://www.pixelglow.com/macstl/
).
Interessante. Ci do un occhio. Grazie.
-riko

 producibile dal miglior compilatore.
Beh, in generale posso essere d'accordo. Ma in assoluto no.
-riko