Newsgroup: it.comp.lang.c++
Titolo: problemi con dichiarazione funzioni

Dato il seguente codice, a parte la potenziale scempiatezza del programma (e
del programmatore, cioč io), genera degli errori in fase di compilazione
riguardo alla dichiarazione delle funzioni. Vi sarei grato se trovaste
l'errore, visto che io non ci riesco.
#include <iostream.h>
#define NULL 0
int *bubblesort(int celle[], int n);
void stampa (int celle_ord[], int n);
int i;
void main()
{
 long int ArraySize;
 cout << "Immettere la dimensione dell'array: ";
 cin >> ArraySize;
 int * p = 0;
 p = new int[ArraySize];
 if(p == NULL)
  cout << "Memoria insufficiente.\n";
 else
 {
  for(i=0;i<ArraySize;i++)
   p[i]=(-ArraySize);
  bubblesort(p, ArraySize);
  stampa(p, ArraySize);
}
int *bubblesort(int celle[], int n)
{
 int j,tmp;
 int *a
 for (i=n-1; i>1; i--)
 {
  for (j=1;j<i;j++)
  {
   if celle[j]>celle[j+1]
   {
    tmp=celle[j];
    celle[j]=celle[j+1];
    celle[j+1]=tmp;
   }
  }
 }
 a=&celle;
 return(a);
}
void stampa(int celle_ord[], int n)
{
 for(i=0; i<n; i++)
  cout << "\t" << celle_ord[i];
 return();
}
--
San Vegeta from Hell
http://www.geocities.com/Area51/Dungeon/8436
http://come.to/Fantasy.it

[...]
Gli indici degli array partono da 0, se parti da 1 ti perdi il primo elemento.
Meglio dichiarare le variabili solo quando si usano:
for (int i= ...  int tmp = ...
In <algorithm> c'e' gia' la swap, per cui la funzione puo' essere semplificata:
  void bubblesort( int array[], int size )
  {
    for (int i = size-1; i > 0; --i)
      for (int j = 0; j < i; ++j)
        if (array[j] > array[j+1])
          std::swap( array[j], array[j+1] );
  }
	Mauro

new non restituisce mai un puntatore nullo, 
Scusa ma questo non mi risulta. Non conosco l'implementazione della
classe 'std', ma in condizioni normali e' corretto testare il
puntatore 'p' con NULL . Infatti in caso di mancata allocazione della
memoria 'p' viene impostato a zero. Certo vi possono essere tanti
altri sistemi per conoscere se la memoria viene allocata o meno
(eccezioni,_set_new-handler,ecc.) ma il discorso di fondo non cambia
...  .
Ciao
~~~~~~~~~~~~~~~~~
MAINARDI Gianfranco
Burago di Molgora (MI)
Italia
Email : 
main...@rete039.it
ICQ# number : 11607125
~~~~~~~~~~~~~~~~~

 > l'errore, visto che io non ci riesco.
 [snip]
Tra le altre cose ti sei "scordato" di fare la delete dell'array allocato con la new.
Generalmente non e' necessario usare le new (o almeno, io sono un fan delle variabili automatiche)
Nel tuo caso, puoi benissimo fare
int p[ArraySize];
cosi'  non devi preoccuparti ne' del buon esito della new ne' tantomeno di liberare 
in seguito la memoria allocata.
Senza considerare che in generale l'utilizzo di variabili automatiche e' piu' efficiente.
Di solito le new sono necessarie quando la memoria deve "sopravvivere" alla
funzione o metodo in cui viene allocata, altrimenti va benissimo una variabile automatica.
Fabio
-- 
They are relatively good but absolutely terrible.
		-- Alan Kay, commenting on Apollos

 (eccezioni,_set_new-handler,ecc.) ma il discorso di fondo non cambia
Ed invece hai torto; se dai un'occhiata a <new> , o leggi lo
Stroustrup (3rd ed.) alla pagina 576 o alla pagina 823, vedi che per
avere un operator new che ritorni zero in caso di fallimento devi
richiederlo esplicitamente: T* p = new(nothrow) T.  Altrimenti non e'
proprio possibile che ritorni zero: lancia un'eccezione bad_alloc
(come ti hanno del resto gia' detto).
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it
A quale versione di compilatore ti riferisci ? 


 (eccezioni,_set_new-handler,ecc.) ma il discorso di fondo non cambia
No, lo standard sancisce che il comportamento di defaul della new sia
in caso di errore di chiamare la new-handler ripetutamente fino a quando
non riesce ad allocare. Se la new-handler non e` stata impostata
esplicitamente con una chiamata a set_new_handler (ovvero se e` stata
eseguita una set_new_handler(0)) lo standard prevede che la new sollevi
l'eccezione std::bad_alloc.
Saluti,
Paolo

  return();
return;
Per il resto sembra che funzioni, a parte il fatto che forse avresti
dovuto riempire l'array con valori casuali e non con un numero fisso per
tutti gli elementi altrimenti come fai a testare la funzione di
ordinamento?
EMG

 A quale versione di compilatore ti riferisci ? 
A nessuna; qui si sta parlando di _linguaggio_, definito da uno
standard ANSI/ISO.  _Qualunque_ compilatore aderente al linguaggio
deve accettare e compilare correttamente delle istruzioni conformi
allo standard.


 
Il manuale del VC++ 5.0 dice che, in caso di fallimento dell'allocazione di
memoria, l'operatore new ritorna 0. Il comportamento di default puo' essere
cambiato impostando un new-handler (set_new_handler) e si puo' anche fare
in modo di sollevare l'eccesione xalloc (ma non dice come), come "descritto
nell'ANSI C++ working paper proposal".
Il manuale del DJGPP (GNU C++) dice che "l'attuale Working Paper richiede
che l'operatore new non ritorni mai NULL"!
Compilatori diversi... Working Paper diversi...
Adesso che e' stato rilasciato lo standard definitivo, chi ha ragione ?
A proposito, dove posso trovare lo standard (magari in formato html
scaricabile) ? (Avevo dei link, ma mi portavano tutti in siti da cui il
documento era stato rimosso)

void stampa (int celle_ord[], int n);
int *bubblesort(int* celle, int n);
void stampa (int* celle_ord, int n);

 documento era stato rimosso)
??????
Questo piacerebbe saperlo anche a me, comunque mi sembra che in rete ci
sia solo il draft.
Saluti,
Paolo


main...@rete039.it
 (Mainardi Gianfranco) writes:

Non so' se lo standard attualmente non ammette che 'new' restituisca
zero in caso mancata allocazione di memoria .
So per certo che il compilatore della Borland C++ 3.1 restituisce NULL
in caso di mancata allocazione di memoria tramite 'new' e d'altronde
questo basta consultarlo sempre sullo Stroustrup 2 edizione alla
pagina 527 e sul Lippman a pag 66 (sempre riferito allo stesso
compilatore) . 
Probabilmente gli ultimi compilatori funzioneranno cosi ........ certo
sarebbe interessante consultare lo standard ANSI per vedere cosa
prevede .


 -- Alan Kay, commenting on Apollos
Sono un principiante e non ho ben capito cosa volevi dire. Mi spiegheresti
in modo piů dettagliato la cosa?
grazie



A dire il vero pensavo che il valore di ogni cella fosse l'opposto del suo
indice nell'array... In questo caso l'ordinamento deve essere fatto per
tutte le celle.
grazie per l'aiuto

...


 A quale versione di compilatore ti riferisci ?
E' lecito riferirsi solo ed unicamente allo standard ISO non al
comportamento di una particolare implementazione del linguaggio.
EMG

 funzione o metodo in cui viene allocata,
Oppure se devi gestire strutture dinamiche non previste nella libreria
standard.
EMG

 void stampa (int* celle_ord, int n);
Guarda che la prima sintassi è perfettamente lecita.
EMG

 indice nell'array...
Allora dovevi scrivere
for(i=0;i<ArraySize;i++)
 p[i]=-i;
EMG

 documento era stato rimosso)
Lo standard si trova solo a pagamento, per esempio dall'ANSI per $18.
Si puo' scaricare liberamente solo il draft del novembre 96, quasi
uguale al definitivo per il linguaggio, ma molto diverso per la libreria
standard.  Si trova in vari siti, per esempio
http://www.maths.warwick.ac.uk/cpp/pub/wp/html/cd2/
	Mauro

 prevede .
Lo standard e' ISO e prevede che in caso di memoria esaurita,
viene chiamato _new_handler, se settato, altrimenti viene lanciata
std::bad_alloc.  
_new_handler puo' :
 - liberare memoria
 - lanciare un'eccezione
 - terminare brutalmente il programma
Se _new_handler ritorna normalmente (senza eccezioni) ma non libera
memoria si rischia un loop infinito.
In nessun caso new ritorna 0.
	Mauro

 prevede .
Io l'ho fatto, e ti ho detto come funzionano.  O non l'avevi capito?


 memoria si rischia un loop infinito.
Non si rischia... e` certo! Perche` lo standard prevede che la new handler
sia continuamente invocata finche` la new non e` capace di allocare la
memoria richiesta.
Paolo
-- 
------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
 
http://www.cli.di.unipi.it/~marotta
------------------------------------------

funzione o metodo in cui viene allocata, altrimenti va benissimo una
variabile automatica.
Sopravvivere in che senso?


 Non so come farlo. Ti dispiace scrivere un pezzo di codice per farlo?
Per lanciare bad_alloc?   throw std::bad_alloc;
ma probabilmente non era questo che intendevi.
Quello che ti serve e' intercettare l'eventuale eccezione lanciata
da new e gestirla. Per esempio:
  try {
    p = new int [1000];
  }
  catch (std::bad_alloc) {
    cerr << "La memoria e' finita!" << endl;
    exit( 1 );
  }
	Mauro

 >Fabio
-- 
The doctrine of human equality reposes on this: that there is no man
really clever who has not found that he is stupid.
		-- Gilbert K. Chesterson

 Sopravvivere in che senso?
La new serve in diversi casi, principalmente quando si ha bisogno di
oggetti non sottoposti alle usuali regole di scoping...


 ------------------------------------------
-- 
Democracy is the name we give the people whenever we need them.
		-- Arman de Caillavet, 1913

    int vettore[size];
La dimensione dell'array deve essere un'espressione costante, per tutti
gli array (anche se per quelli automatici il compilatore farebbe poca
fatica ad accettare anche una variabile). [Stroustrup 3ed., 5.2]
Se si vuole un array di dimensione non nota a priori, bisogna usare std::vector.
Alcuni compilatori (p.e. gcc), accettano anche le variabili come dimensione
degli array automatici, ma e' una estensione.
	Mauro


Oops! Io uso proprio il gcc !
chiedo pubblicamente scusa :-/
-- 
This is a test of the emergency broadcast system.  Had there been an
actual emergency, then you would no longer be here.

 }
Ehm...  Compilando il tuo codice si ottiene un bell'errore...
Questo e' egcs 1.1.1 sotto Solaris 2.5 su una Sun:
foo.cxx: In function `int main()':
foo.cxx:9: warning: ANSI C++ forbids variable-size array `vettore'
Questo e' KAI sotto Digital Unix su un'alpha:
"foo.cxx", line 9: error: expression must have a constant value
     int vettore[size];
Io darei anche un'occhiata allo Stroustrup, pag. 89: "The number of
elements ... must be a CONSTANT expression. ... For example:
void f(int i)
{
  int v1[i] // error: array size not a constant expression
(Il fatto che egcs dia solo un warning e' un'estensione GNU)


   int i;
Non mi risulta che sia standard. So che almeno un compilatore lo
permette ma l'attuale standard (per quanto ne so) non lo consente.
Tempo fa partecipai ad una discussione in merito e venne fuori che
egcs lo consente, ma lo standard no!
Saluti,
Paolo
----------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
----------------------------------------------------------

 service pack, sarà per questo?
Non penso. Credo che la causa sia solamente che il VC++ 5.0 è ormai un
po' vecchiotto e non aggiornato rispetto allo standard.
EMG

 Troverai una spiegazione piu' chiara della mia in un qualsiasi manuale ;-)
Non ne sarei tanto sicuro... :-(
EMG

return 0;
Una curiosità: perchè non posso dichiarare main come void? E' una regola del
linguaggio o è dovuto alla mia particolare main?

E' una regola del linguaggio (sia C che C++).  Il valore ritornato
viene passato al sistema operativo; ed anche se questo non lo adopera,
vi sono sistemi ed ambienti in cui una funzione che ritorna un int ed
una che ritorna void vengono chiamate con meccanismi differenti ---
per cui BOOM.


linguaggio o è dovuto alla mia particolare main?
Lo dice lo standard...(tant'e` che se non metti una return nella main
il compilatore aggiunge automaticamente "return 0")
anche se alcuni compilatori per compatibilita`
all'indietro lo permettono ancora.
Paolo
------------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
  G: Per concludere, possiamo chiedervi di commentare
     l'attuale panorama informatico?
  I: /* l'attuale panorama informatico */
------------------------------------------------------------------

 linguaggio o è dovuto alla mia particolare main?
In C++ (e anche in C) la funzione main() è implicitamente dichiarata
come
int main();
oppure come
int main( int argc, char *argv[] );
e quindi utilizzarla come
void main();
non può essere altro che un errore.
EMG