Newsgroup: it.comp.lang.c++
Titolo: Scope e creazione variabili

Una volta pensavo che scrivendo qualcosa di questo genere
while (qualcosa) {
	int i;
	qualcosadafare;
}
ogni ciclo veniva creata una variabile di nome i e poi distrutta alla
fine del ciclo; il che (spero) è sbagliato.
però mi chiedevo, spesso faccio molti cicli for in questo modo
for (int i = 0; i < 10; i++) qualcosa_da_fare;
for (int i = 0; i < 23; i++) qualcosaltro_da_fare;
è uno spreco di memoria, perché vengono usate due locazioni per
mantenere quell'i che ha senso solo all'interno del ciclo for, oppure
no?
sarebbe meglio
int i;
for (i = 0; i < 10...
for (i = 0; i < 23...
oppure no?
MadMage

oppure no?
Tutto sommato, quanto ci guadagneresti in velocità?
A questo punto meglio la chiarezza ;-)
Ciao
Domenico Barra

 no?
No, non c'è nessuno spreco in quanto la variabile i viene distrutta ogni
volta che finisce il loop.
EMG

 oppure no?
Con il Visual C++ o fai così o definisci un altro contatore

 e perciò da errore di ridefinizione della variabile i
Il VC++ non e' conforme allo standard in questo aspetto.
 
Ciao,
Nicola

for (int i = 0; i < 23; i++) qualcosaltro_da_fare;
Se proprio vuoi una soluzione può essere:
...
{for (int i = 0; i < 10; i++) qualcosa_da_fare;}
for (int i = 0; i < 23; i++) qualcosaltro_da_fare;
...
Luc.

e perciò da errore di ridefinizione della variabile i
Anche se la cosa fosse equivalente (e non lo e'), non c'e' alcuna
ridefinizione della variabile i.

Il Visual C++ non e' C++ se non ti consente di fare questo...
Confermo, non č possibile farlo in VC++ ;)
Da oggi lo chiameremo VC+
Luc.

 }
Ciao,
Nicola

Da oggi lo chiameremo VC+
Scusa ma la mia applicazione l'ha compilata ...
Dov'e' che sbaglio ?

             printf( "ciao sono l'iterazione n.%d\n", i ) ;
Scusa, saro' scemo io, ma non vedo nessun cambiamento tra l'una e
l'altra !...

Microsoft Visual C+(+)?


Sono io che non mi sono spiegato bene. Il problema del VC++ e' che non
gestisce correttamente lo scope della variabile dichiarata all'interno
del for. Secondo lo standard la variabile e' locale al for, per il VC++
e' definita nello scope circostante.
Quindi se copi e incolli il tuo ciclo un'altra volta, dovresti avere un
messaggio di errore riguardante la ridefinizione di i.
Ciao,
Nicola

Sono io che non mi sono spiegato bene.
Anche io ci sono arrivato dopo un po... però ho capito che volevi
duplicare il codice (è stata dura) ^_____^
Luc.

Dov'e' che sbaglio ?
Ma tu non usi il Borland?
Luc.

Microsoft Visual C+(+)?
Gia' ;)
Vedi altro messaggio piu' sotto per spiegazioni dell'accaduto ;)

Ma tu non usi il Borland?
Non solo ;)
Devi essere poliglotta nella vita...

messaggio di errore riguardante la ridefinizione di i.
Hai ragione ! non ci posso credere !
Grazie a tutti per avermelo fatto notare, perche' se mi fosse capitato
in un eventuale programma, avrei perso la testa nel cercare di capire
a cosa era dovuto ! Microsoft non spentisce mai la sua idiozia !...

 }
Questo non è sufficiente. Devono essercene almeno due di cicli for che
definiscono la stessa variabile come indice. L'errore di ridefinizione
indica che lo scope della variabile non è il ciclo stesso come dovrebbe
essere. Sembra anche a me che il VC++ abbia questo difetto ma non ne
sono sicuro.
EMG

 a cosa era dovuto ! Microsoft non spentisce mai la sua idiozia !...
Mah.... non è così scandaloso come sembra. E' semplicemente un problema di
compatibilità, nè ci vorrebbe molto, suppongo, alla Microsoft correggerlo.
Il fatto è che all'inizio il C++ si comportava esattamente come fa il
compilatore della Microsoft: lo scope della variabile era quello che
comprendeva il ciclo for. Poi lo standard ha deciso che è più elegante farla
rientrare nello scope interno del ciclo for. Il punto è che ci sarebbe molto
vecchio codice da riscrivere aderendo allo standard e così aspetteranno
ancora un po' prima di adeguarsi.
Certo, una team intelligente avrebbe messo un bello switch nelle opzioni per
scegliere quale comportamento adottare, però con tutti i soldi che fanno,
non possono mica affaticarsi troppo...

 non possono mica affaticarsi troppo...
Come ad esempio il C++Builder della Borland.
Ciao,
Nicola

Visto che 'sto thread l'ho fatto io, non posso fare a meno di mostrare
tutto il mio disprezzo per VC++.
Io, quando posso, evito sempre di utilizzare prodotti MS. E lo faccio
perché quando mi ci trovo a lavorare c'è SEMPRE qualcosa che va al di
fuori dello standard... ma avranno manie di protagonismo e vogliono
per forza crearli loro gli standard?!?!?
Vedi, ad esempio, l'SQL di Access.
Oppure il "R:" di Outlook Express, che secondo lo standard dovrebbe
essere "Re:"
Insomma, se uno ha un programma scritto in C++ STANDARD che più
standard non si può, c'ha sempre il dubbio che VC++ glielo compila.
Ma che scemenza!
Una domanda: io uso il C++Builder 3.0, volevo sapere, in un programma
così scritto, anche a console, BCB ci mette delle righe di programma
che gli altri compilatori potrebbero non gradire (ma gli standard
niente proprio, eh?), del tipo:
#pragma hdrstop
o, peggio
#include <condefs.h>
e, i peggiori di tutti
USEUNIT("Pippo.cpp")
USExxx("xxx")
non è che nei compilatori/builder nuovi questo fatto non esiste più?
mi sembra totalmente inutile l'utilizzo di USEUNIT, ad esempio,
basterebbe avere un Makefile (e non un bpr... ma perché i bpr sono
diversi dai makefile... e, già che ci siamo, perché le lib di borland
sono diverse da quelle del resto del mondo?).
Tanto più che USEUNIT è una macro fittizia che non è assolutamente
nulla (è definita con DummyNeverDeclared o qualcosa del genere).
VOGLIO LO STANDARD!!!!
MadMage
P.S.: ho visto una sola volta VC++ in azione... considerando la
lentezza di compilazione, rispetto ad un BCB (anche versione 3.0 come
ce l'ho io), direi di ribattezzare VC++ in VC--. ;-D

 sono diverse da quelle del resto del mondo?).
Se vuoi usare l'IDE non hai alternative, altrimenti mi risulta che BCB
5.0 (io uso il 4.0) permetta di creare dei progetti di tipo "console"
senza istruzioni specifiche Borland. Il .bpr invece te lo tieni:
addirittura in BCB 5.0 non e' piu' simil Makefile, ma XML.
Ciao,
Nicola

niente proprio, eh?), del tipo:
Secondo me la vera scemenza e' quella di pretendere che un particolare
compilatore, come il BC++B (ma anche come il VC++), non abbia
estensioni proprie rispetto allo standard.
Stai confondendo pericolosamente.
Una cosa e' dire che un compilatore non rispetta lo standard e una
cose e' dire che un compilatore *ESTENDE* lo standard.
Ci sono dei comportamenti base che ogni compilatore DEVE implementare
per essere conforme allo standard (non credo che esista ancora alcun
compilatore 100% standard), ma lo standard non vieta assolutamente, ad
alcun compilatore, di avere direttive del tipo #pragma o di usare
macro definite in proprio.
Anzi, #pragma e' stata introdotta nello standard proprio per
consentire ai compilatori di avere proprie estensioni.
Quindi, non confondiamo cio' che e' conforme allo standard con cio'
che e' conforme allo standard e al tempo stesso lo estende.
D'altronde, con un compilatore in grado di compilare SOLO codice
standard, ci puoi fare veramente poco.

comprendeva il ciclo for.
Infatti se provo a compilare sta robba su djgpp:
for(int x=0;x<10;x++)faiqualcosa();
for(x=0;x<15;x++)faiqualcosa();
il compilatore mi da due bei warning:
Warning: name lookup of 'i' changed for new ansi 'for' scoping.
Warning: using obsolete binding at 'i'.
Il Ghenio
-----------
LOVELY SARA
Dal lunedi'al venerdi'su Italia Uno alle 8:10
Non perdetevelo...
-----------

ce l'ho io), direi di ribattezzare VC++ in VC--. ;-D
Io grazie al cielo non ho mai avuto il bisogno di adoperarlo, ma ho
sentito molti miei colleghi lamentarsene.


a cosa era dovuto ! Microsoft non spentisce mai la sua idiozia !...
Beh' Microsoft ha *dovuto* fare cosi' per compatibilita' verso codice
preesistente... Mi sembra che in origine fosse previsto che lo scope di una
variabile dichiarata nei cicli for fosse dal ciclo for *in poi*... Dopo le
cose sono cambiate ( lo scope si restringeva solo al ciclo for ) scegliendo
una notazione secondo me piu' coerente ( e che salva codice durante i
copia/incolla selvaggi ! )


Per #pragma ok, perché gli altri compilatori, se non lo conoscono, lo
saltano (questo è ESTENDERE)... però per gli include tipo a condefs.h,
che gli altri compilatori non possiedono, mi costringono a mettere
righe del tipo
#ifdef __BORLANDC__
#include <condefs.h>
#endif
per sperare che anche un djgpp lo possa compilare... lo stesso vale
per il codice di cui parlavamo, perché in un codice scritto in ANSI
C++ il VC++ mi ci deve trovare degli errori e costringermi a
correggerlo???
oppure, ad esempio, per __fastcall che gli altri compilatori non
riconoscono... mi sembra giusto, perché questa è una aggiunta di
Borland e SE VOGLIO la utilizzo, a scapito della possibilità di
riutilizzare il codice da altre parti... ma questa è una scelta (come
bool, true e false), mentre #include <condefs.h>, USEUNIT e compagnia
è un obbligo che mi obbliga a non poter usare altri compilatori.
E questo non è estendere, è CREARE un proprio standard.
O no?


allo standard mentre con il VC++ questo spesso non é possibile.
Come ho detto nel post sopra, #pragma è una estensione, __fastcall è
una estensione, bool, true e false sono estensioni, ma USEUNIT,
#include <condefs.h>, ecc. non sono estensioni, perché mi impediscono
di creare un codice che sia compilabile con altri compilatori.
Giusto?
MadMage


 con altri compilatori.
Sei obbligato a usarli?
Qual e' la differenza rispetto a __fastcall?
	Mauro

 una estensione, bool, true e false sono estensioni,
No, bool, true e false fanno parte del C++ standard.
EMG

preesistente...
Resta il fatto che conferma la sua proverbiale incapacita' di fare
concorrenza in quanto a qualita', nel campo dei compilatori.

O no?
No.
Stai portando la questione su un altro piano che e' quello della
portabilita'. E' chiaro che se usi le estensioni Borland, non puoi
compilare il codice con Visual C++.
Le direttive #ifdef sono spesso usate proprio per questi scopi.
Cioe' per rendere il codice compilabile da diversi compilatori.
E' assurdo pensare, per esempio, che si possa scrivere del codice per
Windows, usando il C++ standard (ed e' sbagliato pensarlo).
CREARE un proprio standard non e' VIOLARE lo standard, ma e' ESTENDERE
lo standard, quando il nuovo standard CONTIENE il vecchio.
Non vuol certo dire rendere il codice portabile, anzi.

Giusto?
Idem. No. Non e' giusto.
bool, true e false sono perfettamente standard, tra l'altro.
La portabilita' del codice, l'estensione e la violazione dello
standard sono tre faccende completamente distinte l'una dall'altra.

Giusto?
Bool, true e false fanno parte dello standard da ormai molti anni e se
non riesci a trovarle significa che hai un compilatore di 10 anni fa.
USEUNIT e #include<condefs.h> sono anch'esse delle estensioni della
Borland, che peraltro non sei obbligato ad usare.


Windows, usando il C++ standard (ed e' sbagliato pensarlo).
A volte pero' le incompatibilita' introdotte sono del tutto
gratuite... ad esempio in VC++ esiste la direttiva "#pragma once"
che indica che il file deve essere incluso una volta sola.
Lo stesso risultato si ottiene con opportuni #define/#ifdef ed
e' possibile, con qualche sforzo, ottenere anche lo stesso
livello di ottimizzazione. Il gcc ad esempio si segna internamente
se un file risulta essere per intero incluso in un blocco del
tipo #if defined(xxx)/#endif ed evita di rileggere il contenuto
del file se il simbolo risulta definito e qualcuno ne chiede
l'#include. Il fatto che i wizard di microsoft generino invece
#pragma once rende il codice non portabile (infatti ignorare il
#pragma in alcuni header porta a degli errori di compilazione).
Riassumendo intendo dire che pur essendo vero che qualche aggancio
alla realta' porta a codice non standard a volte non si prova
nemmeno ad aderire dove possibile.
Riguardo allo scope delle dichiarazioni nei for(...) esiste lo
swith "disable language extensions" che permette di attivare
la semantica standard. Il problema e' che selezionando
quell'opzione non sono piu' compilabili gli header di sistema
per la presenza di estensioni (strutture anonime).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

Il VC++ non e' conforme allo standard in questo aspetto.
Devi disabilitare le estensioni al C++ per rendere lecito i:
for(int i; ...
for(int i; ...
-- 
Tieni per te il Papero se vuoi la mia email
Sito Papero -> 
http://utenti.tripod.it/papero

Qual e' la differenza rispetto a __fastcall?
__fastcall non è un obbligo, nel senso, se voglio fare un prog
standard non uso le dichiarazioni __fastcall.
Ora, non so se è il mio compilatore che è vecchio e nelle versioni
nuove (4 e 5) la cosa è migliore, però se non metto USEUNIT nel
progetto, non mi linka le unit e dato che USEUNIT è definito in
<condefs.h> devo mettere quell'#include.
MadMage

Borland, che peraltro non sei obbligato ad usare.
no?!??!?! allora c'è qualcosa che non va nel mio compilatore... se non
metto le USEUNIT non mi linka le unit al programma... e USEUNIT è
definito in <condefs.h>
MadMage

 Devi disabilitare le estensioni al C++ per rendere lecito i:
mi sapresti dire come?

 MadMage
Scusa se mi intrometto, ma prova a mettere
#include "MiaUnit.h"
al posto di:
USEUNIT MiaUnit.h
Non ho piů installato il BCB3 per verificarlo ma mi sembra che funzioni
Comunque con il BCB4 (che ho trovato in una rivista)
che, comunque, mi sembra molto piů aderente allo standard e
facendo New Application
ti scrive nel file Unit1.cpp:
// -------------------------------------------------------------------------
--
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
// -------------------------------------------------------------------------
--
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
// -------------------------------------------------------------------------
--
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
// -------------------------------------------------------------------------
--
che ovviamente non č standard, ma presuppone che tu voglia usare
le VCL
e nel file Project1.cpp scrive:
#include <vcl.h>
#pragma hdrstop
USERES("Project1.res");
USEFORM("Unit1.cpp", Form1);
// -------------------------------------------------------------------------
--
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
         Application->Initialize();
         Application->CreateForm(__classid(TForm1), &Form1);
         Application->Run();
    }
    catch (Exception &exception)
    {
         Application->ShowException(&exception);
    }
    return 0;
}
che non č, altrettanto ovviamente, standard;
infatti presuppone, oltre alle VCL, che tu stia facendo una
Win32 Application
In piů crea il file .dfm in cui mette i fati della form
Alla fine, pero, se non vuoi usare le VCL tutto puň essere molto piů
standard:
ti fai il tuo bel
int main()
e se vuoi usare codice in un altro file usi:
#include "AltroFile.h"
insomma... tutto come al solito
Poi č ovvio che se usi un RAD, allora vuoi fare applicazioni
usando la grafica (almeno finestre e bottoni...)
A questo punto sei vincolato all' SO e non c'č modo di scrivere tutto in C++
standard.
Io terrei ben separate l'interfaccia grafica dalle parti di calcolo in modo
che cambiando piattaforma tu possa tenere invariate queste ultime.
Di piů, IMHO, non puoi fare...
O no???
Gerolamo

nemmeno ad aderire dove possibile.
Ribadisco che stiamo confondendo gli argomenti.
Se parliamo di portabilita' e' un conto. Se parliamo di violazione
dello standard, e' un altro conto. Sono d'accordo sul fatto che
bisognerebbe aderire laddove si potrebbe, ma questo e' un altro
discorso.

 riutilizzare il codice da altre parti... 
__fastcall e' un'estensione Microsoft, credo.
Ciao,
Nicola

 O no?
Dimenticavo due cose: il tipo bool e' previsto dallo standard e non e'
una estensione Borland; USEUNIT e simili sono richiesti dall'IDE, non
dal compilatore.
Ciao,
Nicola

 <condefs.h> devo mettere quell'#include.
Hai mai provato a compilare da riga di comando? (Gli utenti del
compilatore gratuito ti sanno spiegare come meglio di me)
Ciao,
Nicola

concorrenza in quanto a qualita', nel campo dei compilatori.
Perche' il resto lo fa meglio ?

Perche' il resto lo fa meglio ?
eh eh eh ;)
Hai ragione...
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
-----------------------------------------------------
"There is nothing better for understanding a kangaroo
 than seeing it jump." [D.Grune, C.J.H. Jacobs]
-----------------------------------------------------

mi sapresti dire come?
Project -> Setting -> C++ -> Custumize -> Disable language extension
