Newsgroup: it.comp.lang.c++
Titolo: Per veri smanettoni

Avete presente l'operatore sizeof? Se gli passate il puntatore alla base di
un array allocato dinamicamente con new vi restituisce la dimensione di tale
array. Ora è da tutti risaputo che stabilire la dimensione di un array in C
è cosa non prevista dal linguaggio, tant'è vero che dobbiamo portarci spesso
e volentieri appresso degli "int size" che ci forniscano tale informazione
in tutto il programma. Ora, se l'operatore sizeof è in grado di conoscere la
dimensione di un array, perchè un programmatore non può fare altrettanto,
magari andando a stanare tale informazione lì dove la pesca sizeof? Come
cavolo fa sizeof a sapere tali info? Perchè non ce le possiamo procurare
pure noi come fa lui?
Ho posto questa domanda al mio prof. di Algoritmi e Strutture Dati, la sua
risposta è stata:<< Non lo so. E' una questione che mi porto appresso da
quando ero studente...>>.
_
SiSkO

 SiSkO
-- 
Main's Law:
	For every action there is an equal and opposite government program.

 quando ero studente...>>.
Uhm... temo che quello sia il livello medio degli insegnanti... :-(
EMG

]

Dunque,
l'operatore sizeof, se allocate con una new memoria per 10 interi su un
puntatore ad intero, vi restituirà 10*sizeof(int) quando gli passate il
puntatore! Infatti potete ricavare la dimensione di un array ALLOCATO
DINAMICAMENTE (sennò NON funziona) utilizzando sizeof.
E se non vi basta, provate a pensare alla delete: come fa a sapere quanta
memoria cancellare quando gli passate il puntatore ad una zona di memoria
allocata? Non è un lavoro di precompilazione, lo scopre lui... magicamente!
E in oltre quando dico che non c'è modo di conoscere la dim di un array dico
proprio che o ve la conservate in qualche variabile o NADA, il C (come il
c++) non pone limiti all'indirizzamento dell'array, lo sanno tutti non solo
quelli che hanno studioto dallo Schildt!
Spero di essere stato più chiaro stavolta, scusate se non lo sono stato
altrettanto nel msg di prima,
_
SiSkO

DINAMICAMENTE (sennò NON funziona) utilizzando sizeof.
No, ho fatto casino... deve essere un array NON allocato dinamicamente.
_
SiSkO

_
Questo e' ovvio, ma runtime non viene fatto nulla.
Hai del codice del genere:
...
char v[10];
...
size=sizeof(v);
...
Il preprocessor in fase di compilazione espande il sizeof con un bel
10, perche' prima ha letto che v e' lungo 10. Tutto li', intelliegnza
del compilatore 0.


 quelli che hanno studioto dallo Schildt!
La dimensione di un array la trovi con l'operatore sizeof. Stai ancora
facendo confusione.
EMG

 allocata? Non č un lavoro di precompilazione, lo scopre lui...
magicamente!
piu' che una magia io penso sia una gabola, un accrocchio, insomma un
utilizzare qualcosa che al programmatore non viene mostrato...
sappiamo infatti che il tipo array (tra l'altro in molti sostengono che il
tipo array non esista, ma questo e' un altro discorso...), in C e in C++,
non contiene le informazioni sui suoi bound, pero' se facciamo:
int *elenco = new int[Valore];
con Valore variabile, magari inserito dall'utente in fase di run-time (cosi'
che nessuno mi dica che il compilatore puo' conoscerlo!), quando scriviamo
delete elenco
cancelliamo il primo elemento ovvero elenco[0], ma questo era un esempio, la
cosa interessante e' che scrivendo
delete [] elenco
viene cancellato (deallocato) l'intero vettore elenco[Valore]... meno male
che il tipo array non contiene i suoi bound!
Non so proprio come sia possibile per il compilatore riuscire in questo
intento, piu' che di compilatore si tratta di compilato in esecuzione, a
compile-time non si puo' fare nulla... che venga creata una variabile
nascosta che contiene il bound del vettore da utilizzarsi in seguito? Una
cosa e' certa, non viene fatta una tacca con un pennarello rosso sulla cella
di memoria che si trova in ultima posizione del vettore ;-)... almeno credo,
aspettate che apro il PC e controllo!
Non aggreditemi, cari EMG, Paolo Marotta e gli altri SAPIENTI del NG, se
sono stato poco preciso... newsgrouppando si impara!
Ciao Davide
/ - / - | - \ - \
Davide Piras
New (
pir...@engineer.com
)
Old (
pir...@iname.com
)
\ - \ - | - / - /

quando ero studente...>>.
Capisco che non si possa sapere tutto, ma se e` tanto tempo che si pone
la domanda, perche` non e` andato a cercare una risposta sui libri?
Ma forse non era un argomento cosi` importante per lui...
Paolo
P.s.
  La faq si allunga!!!!!
-----------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------

  il simbolo sizeof() viene viene risolto direttamente dal precompilatore
No, viene risolto dal compilatore... il precompilatore non ha visione di
alcuna informazione semantica, tanto meno di tipo.
E d'altronde le direttive per il precompilatore iniziano con #
Paolo


 nascosta che contiene il bound del vettore da utilizzarsi in seguito?
Diversamente dal C, il C++ deve conoscere le dimensioni di un array allocato
dinamicamente, cosi' da poter chiamare - dove richiesto - i distruttori
degli oggetti allocati. La dimensione viene memorizzata con la stessa
tecnica usata dalle vecchie malloc() e free() del C. Vi siete mai chiesti
come fa la free() a sapere quanti byte deve liberare ? Per ogni blocco
allocato la malloc() memorizza in un header (che fa parte del blocco stesso)
la dimensione e passa al chiamante la locazione di memoria successiva
all'header. Per i bound il C++ dovrebbe fare piu' meno la stessa cosa (in
realta' non ho mai verificato, ma mi sembra l'unica soluzione ragionevole):
/* Codice non provato: solo come esempio */
typedef struct {
  size_t size;
  size_t elements;
} header_t;
void *alloc(size_t size, size_t elements)    // o new...
{
  void *p=GETMEM(size*elemts);
 header_t *h=(header_t *)p;
 h->size=size;
 h->elements=elements;
  return  h+1;
}
free(void *p)
{
  header_t *h=(header_t *)p;
 h=h-1;
 FREEMEM(h, h->size*h->elemets);
}
E come per magia le funzioni di allocazione conoscono le dimensioni.
Aggiungere chiamate a costruttori e distruttori a piacere...
A questo punto sembrerebbe molto semplice ricavare la dimensione a runtime,
ma in realta manca ancora qualcosa. Come fa il compilatore a sapere
l'origine di un puntatore e se si tratta di un array:
int *p;
....
p=new int[100];
....
p+=10;
...
--p;
x=sizeof(p); !!!! Impossibile determinare l'origine
p e' un int *, il compilatore non puo' dsapere da dove viene il suo
contenuto e a quale elemento di un array si riferisce. p non punta piu' al
primo elemento, e anche se puntasse ancora al primo, il compilatore non
potrebbe saperlo. Diventa impossibile usare la sizeof, che, per precisare,
non e' ne usa funzione ne un'operazione di preprocessore, ma un operatore
(keyword del linguaggio) che determina la dimensione di un tipo dati
(direttamente o tramite una istanza).
Saluti, Alberto.

 proprio che o ve la conservate in qualche variabile o NADA,
Suppongo che questo dipenda appunto dal fatto che lo standard non
garantisce che quel numero (10 nell'esempio precedente) sia scritto
proprio in quella posizione che ho trovato io
(prima del primo elemento dell'array).
[SNIP]
Marco Guidi

aspettate che apro il PC e controllo!
 Questo scrive il "Linguaggio C++" di Bjarne Stroustrup :
"Si osservi che per deallocare lo spazio allocato da new, delete deve essere
in grado di determinare le dimensioni dell'oggetto
Ciò implica che un oggetto allocato mediante l'implementazione standard di
new occuperà una quantità di spazio leggermente superiore a quella di un
oggetto statico (di solito una parola in più)."
Non ho provato ma credo che un buon posto dove aggiungere questo dato sia
nel byte immediatamente prima dell'indirizzo  &(var[0]) ...
Ciao
    Alessio C.

 cancelliamo il primo elemento ovvero elenco[0],
No, è un errore semantico. Sicuramente non cancella solo il primo
elemento. Non è possibile deallocare singolarmente un elemento di un
array allocato dinamicamente. O tutto o niente.
EMG

   La faq si allunga!!!!!
Però stiamo attenti: una FAQ deve essere una FAQ e non la raccolta dei
messaggi di it.comp.lang.c++. Giusto?
EMG

> quelli che hanno studioto dallo Schildt!
No, se
int array[10];
size_t ArraySizeInChars = sizeof(array);
funziona correttamente, perche a compile time e` nota la dimensione
dell'array (10) e quella di ciasun elemento (sizeof(int)).
Non funziona con i puntatori perche` a compile time non puoi sapere
se il puntatore punta ad un elemento semplice oppure ad un
array, infatti tutto cio` che si puo` dire e che il puntatore punta
almeno ad un elemento.
Comunque tutti questi problemi si risolvono efficacemente con i
template o la OOP (a scelta).


 x=sizeof(p); !!!! Impossibile determinare l'origine
Questa perň č un'operazione che non si puň fare comunque, sia che il
puntatore punti al posto giusto sia che sia stato spostato.
EMG

 wrote in message
3826A45D...@flashnet.it...

Infatti, intendevo mettere in evidenza che, anche potendo recuperare le info
di allocazione (ipotizzando una sizeof() in grado di farlo), non sarebbe
stato comunque possibile determinare la size dell'array. Scusate se non sono
stato chiaro.
Saluti, A.

p+=10;
A questo punto credo che eseguire "una delete[] p" sarebbe
undefined behaviour, o sbaglio?


No, ho fatto casino... deve essere un array NON allocato dinamicamente.
Probabilmente non ti e` chiaro che sizeof viene risolta (eseguita) a
*compile time*, non a run time!
#include <iostream>
using namespace std;
typedef int (*ArrayPtr)[10];
int main() {
  ArrayPtr Arr;
  cout << sizeof(*Arr) << endl;
  char b;
  cin >> b;
}
Il risultato e` 40 perche sulla mia architettura sizeof(int)==4
E nota che Arr non e` inizializzato in alcun modo, il valore di sizeof
viene calcolato unicamente guardando alla dichiarazione.


messaggi di it.comp.lang.c++. Giusto?
Ovviamente...
Solo che a me sembrava una domanda degna della faq perche` mi pare
che in passato ci siano gia` state domande del genere...
Ad ogni modo se si ritiene che non sia cosi` si puo` evitare.


sono stato poco preciso... newsgrouppando si impara!
Non prenderla come aggressione, ma solo come correzione... a suo tempo
ci siamo passati pure noi e (almeno io) di tanto in tanto qualche 
cantonata continuo a prenderla!



Non sbagli, ma non lo ho considerato in quanto non cambia la discussione su
sizeof.
In effetti si potrebbe ipotizzare un operatore sizeof dinamico in grado di
determinare la dimensione di un array dinamico con lo stesso sistema usato
dalla delete, e pertanto vincolato dagli stessi limiti.
Saluti, A.

dalla delete, e pertanto vincolato dagli stessi limiti.
E' questo che non mi è chiaro: come mai "sarebbe ipotizzabile" e non è in
pratica stato realizzato? Evidentemente ci sono degli impedimenti...?
_
SiSkO

nel byte immediatamente prima dell'indirizzo  &(var[0]) ...
Questo significherebbe che accedendo a var-1 si dovrebbe poter conoscere la
dimensione di var... non sarà troppo facile?
_
SiSkO

che il tipo array non contiene i suoi bound!
Oh, finalmente vedo che la questione è stata colta, chiedo scusa per la
confusione di prima...
_
SiSkO

dalla delete, e pertanto vincolato dagli stessi limiti.
Questo introdurrebbe degli overhead (in contrasto alla filosofia del 
C++), d'altronde queste cose in C++ sono facilmente implementabili
(in 3 secondi) all'occorrenza. Oltretutto c'e` gia` std::vector bello 
pronto se non erro (anche se std::vector puo` avere overhead molto
pesanti in talune situazioni).


dimensione di var... non sarà troppo facile?
Non e` questione di facilita`, ma semplicemente non puoi farci 
affidamento, lo standard non ne parla e la cosa protrebbe cambiare
non solo da piattaforma a piattaforma (a parita` di compilatore), ma
anche (molto probabilmente) tra compilatori diiversi o anche tra
versioni diverse dello stesso compilatore. A maggior ragione se ti
servi poi di gestori della memoria di terze parti...


 dimensione di var... non sarà troppo facile?
Solo che in C++ l'accesso ad un elemento fuori dal range [0, sizeof
array] (nota l'intervallo chiuso: si può accedere ad una posizione, una
sola, dopo l'ultima) è "undefined behaviour".
EMG

 pratica stato realizzato? Evidentemente ci sono degli impedimenti...?
Credo che sia a causa della compatibilita' con il C e relative librerie.  Il
compilatore non puo' distinguere fra blocchi allocati con new piuttosto che
con malloc() e la malloc() non memorizza le info sui bound. L'informazione
sulla dimensione totale c'e' ma e' arrotondata al blocco minimo di
allocazione e quindi non e' adatta per calcolare gli elementi con una
divisione per sizeof(tipo).
Inoltre, ma credo che questo sia compiler-dependent, in mancanza del
distruttore, il numero di elementi potrebbe non essere memorizzato nemmeno
dalla new (degenera in una malloc).
In pratica (il DJGPP) la new di unaclasse senza distruttore diventa:
void *operator new(size_t size)
{
  return malloc(size);    // magari non usa proprio la malloc, ma e' il
concetto che conta;
}
Mentre con il distruttore:
void *operator new(size_t size)
{
  size_t *x=malloc(size+sizeof(size_t));
  x[0]=size;
  return x+1;
}
Questo si puo' facilmente risolvere memorizzando sempre il numero di
elementi, ma non si puo' risolvere il problema della compatibilita' con la
malloc().
Se avete il DJGPP, provate questo:
#include <iostream.h>
template <class T> size_t dynamic_sizeof_pod(T *x)
  // sizeof per un tipo base
{
  return ((unsigned int *)x)[-1] & ~0x1;
}
template <class T> size_t dynamic_sizeof(T *x)
  // sizeof per classi
{
  return ((unsigned int *)x)[-2] & ~0x1;
}
template <class T> size_t dynamic_arrayitems(T *x)
  // numero di elementi (confrontatelo con dynamic_sizeof()/sizeof(T))
{
  return ((unsigned int *)x)[-1];
}
class prova_c
{
public:
  char c;
  prova_c() { c=1; }
  ~prova_c() { c=0;}
};
int main()
{
  char *c=new char[11];
  prova_c *p=new prova_c[11];
  cout<<endl;
  cout<<"char[11]; "<<dynamic_sizeof_pod(c)<<'
'<<dynamic_sizeof(c)/sizeof(char)<<' '<<dynamic_arraysize(c)<<endl;
  cout<<"prova_c[11]: "<<dynamic_sizeof_pod(p)<<'
'<<dynamic_sizeof(p)/sizeof(prova_c)<<' '<<dynamic_arrayitems(p)<<endl;
  return 0;
}
Come noterete, nel caso char la sizeof_pod e' sbagliata a causa
dell'arrotondamento all'intero superiore, mentre la dynamic_sizeof e
dynamic_arrayitmes sono completamente sbagliate. Nel caso di prova_c,
sizeof_pod sbaglia (cerca l'info sulla sizeof totale dove ora c'e' il numero
di elementi), la dynamic_sizeof sbaglia per arrotondamento, mentre la
dynamic_arrayitmes funziona.
Poi provate a togliere il distruttore da prova_c... perderte l'info sul
numero di elementi.
Saluti, A.

In soldoni, anche se ho 
int * p;
p = new int[100];
sizeof(p)	equivale a	sizeof(int *)
sizeof(*p)	equivale a	sizeof(int)
ovvero sizeof di una variabile e' solo una comodita' per non doversi
andare a ricercare nel codice la dichiarazione della variabile, e magari
riportarla sbagliata.
Ciao,
Nicola

In realta' e' sufficiente il membro size. Al gestore della memoria non
interessa cosa ci finisce dentro.
Ciao,
Nicola

 EMG
Col massimo rispetto per il lavoro avviato e benche mi pare che la
situazione sia migliorata, talvolta ho la sensazione che per realizzare
la FAQ sarebbe sufficiente rimuovere dal newsgroup i messaggi OT e
quelli PD (platform dependent) ;-)
Ciao,
Nicola

 quelli PD (platform dependent) ;-)
Hai perfettamente ragione. Io ho cercato di battermi per ottenere questo
ma non sono riuscito a combinare niente se non a far arrabbiare
qualcuno.
EMG

 aspettate che apro il PC e controllo!
Credo che la soluzione possa essere o nelle funzioni del SO, oppure nel modo
in cui il compilatore gestisce lo heap.
Nel primo caso, a run-time avviene che la new chiede al SO un po' di
memoria, di cui sa le dimensioni (ma il compilatore no).
Con la delete, si chiede al SO di cancellare la memoria precedentemente
allocata, ed č il SO a segnare con il pennarello l'area allocata, ma si
guarda bene dal dire al programma quanta era.
Probabilmente sarebbe possibile implementare una funzione sizeof che
implementi una chiamata al SO per chiedere la memoria, ma il C/C++ non la
mette a disposizione.
Con il DOS tutto ciň era cosě (sempre che il compilatore decidesse di
appoggiarsi completamente alle API rinunciando ad una gestione in proprio).
--
Alessandro Monti


Al gestore di memoria no, ma alla delete si. Size e' la dimensione del
blocco "grezzo",  >=sizeof(tipo)*numero_di_elementi, in quanto, di solito,
la memoria viene allocata arrotondando al "taglio" minimo superiore, di
dimensione dipendente dall'implementazione. Prova ad allocare da 1 a 4 char:
i compilatori per CPU a 32 bit allocheranno sempre non meno di 4 byte (32
bits).
Il numero di elementi e' necesario per sapere quanti distruttori chiamare:
A.


Non ci sarebbe nessun overhead. la "dynamic_sizeof" userebbe info gia'
memoriazzate per la delete.
Sul fatto che ci sono gia' i vector e che sarebbe facile implementare una
classe per portarsi dietro la dimensione, sono d'accordo.
Saluti, A.

 }
Mi sono dimenticato alcune osservazioni finali:
A causa della compatibilita' con il C (malloc) e per un'evidente problema di
sintassi (come faccio a dire alla sizeof che voglio la size dell'array
dinamica e non del puntatore ?) la sizeof non puo' supportare la memoria
dinamica. Inoltre perderebbe la sua caratteristica statica (calcolata a
compilation-time).
Sarebbe possibile introdurre un nuovo operatore, diciamo dynamic_sizeof(),
per ricavare la dimensione dei blocchi di memoria dinamica (quella realmente
utilizzata, non quella allocata), integrato nel linguaggio e nel run-time di
ogni compilatore. Non ci sarebbero problemi di portabilita', nel senso che
sarebbe al livello della delete. Questo operatore avrebbe gli stessi vincoli
di utilizzo della delete. L'unico overhead richiesto sarebbe la
memorizzazione della dimensione (o numero di elementi) anche quando non
necessario (come nel caso di classi senza distruttore).
A questo punto si torna alla domanda originale: perché lo standard non lo
prevede ?
L'unica motivo che mi viene in mente e' che, al pari della delete, sarebbe
un operatore pericoloso. Deve essere applicato solo a puntatori ottenuti con
una new. Mentre da delete deve essere fornita per forza, il dynamic_sizeof
non e' necessario e, all'occorrenza, puo' essere facilmente costruito, come
giustamente ha gia'  fatto notare P. Marotta.
Saluti, Alberto.

memoriazzate per la delete.
Mi riferivo ad un confronto con la sizeof...
L'overhead ci sarebbe perche` la dynamic_sizeof andrebbe eseguita a
run time in un tempo non nullo. 


 prevede ?
[...]
1) Perche' e' inutile usare un modo complicato e insicuro per recuperare
   un'informazione nota in partenza, ovvero cosa il programmatore ha
   chiesto di allocare.
2) Perche' l'operatore da te descritto darebbe un risultato
   inconsistente o quantomeno poco utile nel caso di strutture dati
   complesse, tipo alberi o liste, a meno di una navigazione ricorsiva
   della struttura.
3) Perche' l'operatore porrebbe dei vincoli inaccettabili nell'override
   di new o delete, pena l'invalidazione della definizione di default
   dell'operatore stesso.
In generale con l'avvento dell'STL mi pare che questo discorso perda di
interesse.
Ciao,
Nicola

>typedef int (*ArrayPtr)[10];
Una dichiarazione di puntatore ad array "delimitato" (a 10 elementi) non 
ha nessun valore aggiunto, no?
il C++ non ha il controllo a run-time dei limiti di un array, quindi, e' 
sempre possibile scrivere
ArrayPtr[11] = 32767;
-- 
universe::earth::internet::albion->Greetz++;
 
darX...@tin.it
 
alb...@libero.it
  Fido 2:335/234.21   
http://darxstar.cjb.net
  ICQ UIN# 11151997 - eggdrop on demand
<the trees that whisper in the evening...>

>realta' non ho mai verificato, ma mi sembra l'unica soluzione ragionevole):
Ed e' per questo che una malloc(1) oppure, per restare in topic un codice 
del tipo
char *ptr = new char[1];
alloca di fatto sempre dai 4 ai 16 bytes, quello e' lo spazio dell'header 
(che si trova sempre a  *(ptr-sizeof(Header)), di fatto la memoria viene 
allocata N bytes "dietro" il puntatore)
La dimensione effettiva dell'header a quanto ho potuto constatare e' sia 
compiler-dependent, ma molto piu' spesso os-dependent, visto che di 
solito la struttura header che usa il compilatore non e' nient'altro che 
un elemento della lista linkata che quasi tutti i sistemi operativi usano 
per allocare memoria virtuale in un segmento dati che usa la paginazione
(Ma queste cose qui non si dicono, i frequentatori di questo NG ignorano 
anche l'esistenza del processore :)) )
Apporpo'....Enrico, Paolo....siete tutti qui adesso? che fine ha fatto la 
CLANG.ITA? ...beh, tanto meglio! sono felice di avervi ritrovati qui! :) 
ci manca solo l'ex Moderatore della CLANG e siamo al completo! :)


 interesse.
Su questo sono d'accordo, in generale (le STL sono piu' costose).
Saluti, Alberto.

 compiler-dependent, ma molto piu' spesso os-dependent, visto che di
Spero non tanto spesso. La gestione dello heap dovrebbe essere sempre
compiler-dependent, implementata nelle librerie del compilatore. Questo di
appoggia a una routine di sistema (in UNIX e' sbrk()), relativamente
"costosa", a cui di solito si richiedono blocchi piu' grandi (il taglio
minimo dipende all'archittettura: nei sistemi con paginazione non e'
inferiore ad una pagina - tipicamente 4K) da cui le librerie C/C++
costruiscono un lista privata del processo (e nel gestirla non bisogna
occuparsi del multiprocessing, ma solo dell'eventuale multithreading).
Ma ormai siamo decisamente Off-Topic.
Saluti, A.

CLANG.ITA?
CLANG.ITA???


   dell'operatore stesso.
Credo che questo sia il problema maggiore, e comunque quando simili
informazioni servono e` logico e naturale farle diventare parte 
esplicita dell'oggetto, anche per garantire la portabilita` del codice.
Un operatore dinamico che faccia affidamento su cosa fa la
new avrebbe lo svantaggio di essere molto vincolato al meccanismo di
new impedendo l'uso diretto (se mai qualcuno pensasse fosse necessario) 
di malloc (e comunque come distinguere tra new e malloc?).
Ci sarebbero insomma una serie di feedback da non sottovalutare.


ha nessun valore aggiunto, no?
Non esattamente, non hai nessun boud checking, ma la sizeof ti riporta
come valore NumeroElementi*sizeof(Elemento)... Ed e` questo che
io volevo mostrare.
Come sempre la filosofia del C++ e` quella di non imporre overhead che 
invece il boud checking imporrebbe. Se ti serve, semplicemente usi delle
classi ad hoc invece degli array primitivi.


Su questo sono d'accordo, in generale (le STL sono piu' costose).
Concordo pienamente.


 ci manca solo l'ex Moderatore della CLANG e siamo al completo! :)
Tanto qui devono venire (a meno che non vadano nei newsgroups in
inglese...).
EMG

 CLANG.ITA???
Si, FidoNet.
EMG


Vedi risposta precedente.
Saluti, A.

 wrote in message
3827D865...@flashnet.it...

Piccola pignoleria: si puo` *fare riferimento a* una posizione dopo
la fine di un array, ma non vi si puo` *accedere*.  Ovvero:
    const int N = 23;
    int x[N];
    int* p = &x[N];    // OK ("fa riferimento")
    *p = 0;                // NON ok ("accede")
    int i = *p;            // NON ok ("accede")
Le linee che ho segnato come "NON ok" danno undefined behavior (o,
ma solo in Inghilterra, undefined behaviour:-).
Alex

>inglese...).
Eh eh, infatti, li aspettiamo! :)


>classi ad hoc invece degli array primitivi.
Beh, e' vero, il valore aggiunto e' il valore di ritorno di sizeof()..
ad essere sinceri io ignoravo anche che era possibile usarlo su di un 
array, da quando programmo in C++ non l'ho MAI fatto....


 ma solo in Inghilterra, undefined behaviour:-).
Sul mio dizionario di inglese è riportato solo il termine "behaviour".
???
EMG

 
In Inghilterra varie parole si scrivono tradizionalmente con un
finale in "our" (colour, labour, behaviour, ...), mentre in USA le
stesse parole si scrivono con finale in "or" (color, labor, behavior).
(Lo spelling "inglese" richiama lontane radici storiche, che
risalgono all'invasione Normanna; quello "americano" e` assai
piu` vicino alla pronuncia che le parole hanno da alcuni
secoli a questa parte).
Lo Standard C++, pubblicato dalla ISO, utilizza "behavior".
Ti ho detto che ero in ispirito di pignoleria in quel momento!-)
Alex

 Sul mio dizionario di inglese è riportato solo il termine "behaviour".
Tanto per chiarire: in Inghilterra varie parole si scrivono con finale
in "our" (colour, labour, behaviour), in USA (e nella maggior parte
del mondo) in "or" (color, labor, behavior).  Il testo dello standard
C++ accettato dall'ISO dice "undefined behavior".
Questa e` una pignoleria proprio piccola piccola...:-).
Alex