Newsgroup: it.comp.lang.c
Titolo: FAQ 13 - Il nome di un vettore è equivalente al puntatore al suo primo elemento ?

Anche questa č vecchia e qualcuno l'aveva fatta bene. Purttroppo č troppo
vecchia e cosě ve la devo richidere (piů frequently asked di cosě...;-)
Ciao
Marco
--
Marco Coppo
University Of Sheffield

 vecchia e cosě ve la devo richidere (piů frequently asked di cosě...;-)
Bisogna partire dicendo che un array ed un vettore sono due tipi di dati
diversi. Il primo č un tipo aggregato che permette di memorizzare lo
stesso tipo di dato uno dopo l'altro in memoria ed individua questa
memoria (che viene allocata automaticamente o staticamente a seconda di
come viene definito l'array) con un unico identificatore e consente
l'accesso ai suoi elementi tramite indice (con l'operatore []).
Di contro, un puntatore č una variabile semplice atta a contenere un
indirizzo (pertanto tutti i puntatori, in una data macchina, hanno
uguale dimensione). Un puntatore si puň far puntare ad un'area di
memoria allocata dinamicamente ed adatta a contenere il tipo di dato che
si vuole gestire attraverso il puntatore. Il puntatore stesso č
tipizzato in quanto soggetto alla cosiddetta aritmetica dei puntatori
che consente di passare da un elemento all'altro in memoria (ammesso che
sia stato allocato spazio per piů di un elemento) utilizzando
semplicemente l'operatore ++ o comunque un operatore di somma. A
differenza dell'array, il puntatore puň essere riassegnato per farlo
puntare in qualche altro posto.
La confusione che a volte si sente tra array e puntatori deriva dal
fatto che in un'espressione il nome dell'array viene convertito
automaticamente nel puntatore al suo primo elemento (ad esempio
passandolo come parametro ad una funzione). Ci sono solo tre eccezioni a
questa regola:
1. L'operatore sizeof().
2. L'operatore & (addressof).
3. Le stringhe costanti utilizzate per inizializzare un array.
In questi tre casi l'array non viene convertito al puntatore al suo
primo elemento.
EMG

 diversi. 
Scusa enrico se ti controribatto su una cosa.
Per quello che hai detto tu array=vettore un mio amico fu bocciato
ad un esame perchè :
array = matrice bi o multidimensionale
array monodimensionale = vettore.
scusate l'intrusione e ciao.
ps: qualcuno di voi programma in c/c++ su mac ?
ciao

 uguale dimensione).
Non e' sempre vero: in macchine che indirizzano memoria in modalita' reale c'e'
differenza tra la dimensione di un puntatore 'near' (16 bits) e un puntatore
'far' (32 bits)
Ivan Molella

 array monodimensionale = vettore.
Certo, è stata una svista. Volevo dire "un array ed un puntatore" non
"un array ed un vettore".
EMG

 'far' (32 bits)
near e far sono un obbrobrio che ormai non viene piů utilizzato neanche
nell'ambito nel quale č stato ideato. Stendiamoci sopra un velo pietoso,
per favore.
EMG

 per favore.
Resta il fatto che chi ha letto il tuo messaggio,poteva capire che la cosa fosse
valida anche su un compilatore dos in modalita' reale,il che  non e' cosi', ed anche
se tu usi strumenti piu' avanzati non e' detto che qualcun'altro faccia lo stesso.
Ivan Molella


Uno puň anche utilizzare compilatori che non dispongono dei tipi float e
double (HiSoft C per lo Spectrum) o per i quali la prima funzione
invocata si chiama winmain() invece che main() (tutti i compilatori per
Windows, credo) ma questo non significa che uno debba tenerne conto
quando parla del C, non ti pare?
EMG

 (pertanto tutti i puntatori, in una data macchina, hanno uguale dimensione)
  Hai ragione, ma quello che tu hai detto non era riferito al linguaggio c in se ,bensi' a
piattaforme di ogni genere,e portato nel caso specifico di un 80286 in modalita' reale
rende l'affermazione non corretta,poiche' per indirizzare una variabile nello stesso
segmento utilizzo un puntatore di  16 bits,mentre se mi devo riferire ad un'area di
memoria (del buffer video x esempio) in un altro segmento utilizzo un puntatore a 32
bits:segmento e offset.
Il principio della tua affermazione  e' giustissimo,soltanto non puo' essere adottato per
il 100% delle piattaforme
Ivan Molella

> (pertanto tutti i puntatori, in una data macchina, hanno uguale dimensione)
La questione e' implementation-dependent.
--
Andrea Laforgia (
andrea_...@bigfoot.com
)
---------------------------------------------

 La questione e' implementation-dependent.
Forse avrei dovuto dire "tutti i puntatori, in un dato compilatore,
hanno uguale dimensione". Se così non fosse il seguente codice non
funzionerebbe:
#include <stdio.h>
struct S;
void pippo( struct S *p )
{
/*  printf( "%d\n", p -> n ); */
    printf( "%ld\n", sizeof( p ) );
}
struct S { int n; };
int main()
{
    struct S s;
    s.n = 123;
    pippo( &s );
    return 0;
}
Il compilatore è in grado di conoscere la dimensione del puntatore
passato alla funzione pippo() senza sapere ancora come sarà fatta la
struttura a cui punta. Mentre non è in grado, ovviamente di accedere ai
suoi membri fino a che non ne viene data la dichiarazione completa
(togliendo infatti il commento si ottiene l'errore "dereferencing
pointer to incomplete type").
Altro esempio. Il seguente codice compila senza errori nonostante A non
sia definita ma solo dichiarata:
#include <stdio.h>
struct A;
struct B
{
    struct A *a;
};
int main()
{
    struct B *b;
    return 0;
}
Questo perché il compilatore conosce ciò che gli serve in questa
situazione e cioè la dimensione dei puntatori che è indipendente dai
tipi puntati.
EMG

Capisco bene quello che dici e sono pienamente daccordo,ma resta sempre la
peculiarita' del caso che ho spiegato prima:
In modalita' reale sizeof(void *) != sizeof(void far * ),anche se il tipo (void far
*) e' un implementazione particolare di un determinato tipo di piattaforme.
Ivan Molella


Va bene. Allora direi di mettere nella trattazione generale il tipo
puntatore standard e poi citare a parte l'esistenza di questi
modificatori non standard.
EMG

 EMG
Concordo. Lo includerò !
Ciao
Marco
Marco Coppo
Univeristy of Sheffield

hanno uguale dimensione". 
Non so che cosa dica lo standard a proposito. A me questa sembra una
cosa ovvia, ma la dimensione di un puntatore tra diversi compilatori
puo' essere differente. Specificare in una faq che tutti i puntatori
hanno stessa dimensione e' a mio avviso inutile, in quanto sarebbe
come dire : tutti gli int hanno uguale dimensione (e' ovvio che sia
cosi').


Alla fine di tutto, non sarebbe meglio tornare alle vecchie regole del C, e
cioč che il tipo "puntatore" riguarda solo il compilatore, e che tutte le
operazioni su di esse, meno quelle garantite dal linguaggio, sono
platform-dependent?
Ovvero: potrei anche avere un compilatore che per puntare gli int usa 16 bit
e per i float ne usa 32, ma del resto il linguaggio non dice in nessun punto
che posso usare un puntatore ad int su un tipo float, no?
Certo sarebbe un compilatore un po' strano, ma potrebbe lo stesso garantire
che:
int *intero;
float *reale;
...
reale = (float *) intero;
Compili, anche se non capisco a cosa possa servire.
Ovvero, si smazzerebbe lui l'onere di cambiare le dimensioni del puntatore
quando necessario.
Se invece dicessi:
reale = intero;
Allora sono gią pronto ad aspettarmi qualcosa di strano...
--
Alessandro Monti

 cosi').
Non e' tanto ovvio, in quanto la questione e' nata tenendo conto che in
compilatori che lavorano in modalita' reale la dimensione di ( void *)
!= (void far *),anche se questa e' un eccezione di piattaforma.
Ivan Molella

e per i float ne usa 32
No, questo no, il tipo "puntatore" prescinde dal tipo puntato.
Puntatore e' un tipo di per se' ed in quanto tale ha una sua lunghezza
fissa.


 cosi').
Non e' vero.  Ad esempio nel Cray l'oggetto indirizzabile e' di
64 bits; i puntatori a carattere sono costituiti da un
puntatore-a-oggetto-di-64-bits con appeso un offset, e sono piu'
lunghi dei puntatori-a-oggetto.
In generale, niente garantisce che puntatori a tipi differenti
non abbiano dimensioni differenti
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 cosi').
Non mi sembra la stessa cosa. Un puntatore a char e un puntatore a long
sono due tipi diversi e dire che hanno necessariamente la stessa
dimensione potrebbe, al contrario, essere sorprendente (ma chiaramente
non deve esserlo) se uno pensa alla differenza di dimensione che invece
c'č tra un char e un long. E poi anche Bruce Eckel ne parla nel suo
Thinking in C++.
EMG

 platform-dependent?
Forse intendi riferirti alle operazioni implementation-defined? Lo
standard parla di tre tipi particolari di operazioni: le
implementation-defined che possono avere qualsiasi comportamento che
perň deve essere documentato, le unspecified simili alle precedenti ma
che non č necessario documentare e le undefined che non devono avere
alcun effetto. Tutte e tre sono da evitare nell'ottica di una
programmazione portabile. Parlando delle operazioni portabili, queste
sono garantite dallo standard e non riguardano il particolare
compilatore utilizzato.
EMG

 non abbiano dimensioni differenti
Uhm... a questo punto bisognerebbe proprio sapere cosa dice esattamente
lo standard. Se è come dici tu allora anche Bruce Eckel ha sbagliato nel


 suo Thinking in C++.
Beh, qui si parla di C e non di C++...  Non sono a Padova, e non ho lo
standard qui; ma sulla rete c'e' il rationale
(
http://www.lysator.liu.se/c/rat/title.html
), e li al punto 3.2.2.3
puoi leggere: 
1) ... maximally portable code may not assume any necessary
correspondence between different pointer types and the integral types.
quindi: non e' detto che un pointer possa essere rappresentato in uno
dei tipi interi, ma puo' richiedere una tipizzazione propria (tipo due
interi, o simile)
2) Nothing is said about pointers to functions, which may be
incommensurate with object pointers and/or integers.
Quindi, quanto meno, esistono due tipi di pointers che SICURAMENTE
possono avere necessita' di rappresentazioni distinte: i pointers a
funzione e tutti gli altri.
E' parecchio che non uso un Cray, ma sono sicuro di ricordare bene
quello che ho affermato; un pointer a parola era di 48 bits, ed un
pointer a carattere era di 64.  Chiaramente un compilatore puo'
mascherare la cosa mettendo tutto in una parola di 64 bits e
sprecandone 16 se del caso...  C'e' qualcuno che ha lo standard a
portata di mano?  Se no, aspettate dopo il 15 febbraio quando torno a
Padova...


 suo Thinking in C++.
Secondo le FAQ di Steve Summit sembrerebbe propio di si.
Question 5.6
If NULL were defined as follows:
        #define NULL ((char *)0)
wouldn't that make function calls which pass an uncast NULL work?
Not in general.
***************************************************************
The problem is that there are machines which use different internal
representations for pointers to different types of data
***************************************************************
 The suggested definition would make uncast NULL arguments to functions
expecting pointers to characters work
correctly, but pointer arguments of other types would still be
problematical, and legal constructions such as
        FILE *fp = NULL;
could fail.
Nevertheless, ANSI C allows the alternate definition
        #define NULL ((void *)0)
for NULL. Besides potentially helping incorrect programs to work (but only
on machines with homogeneous pointers, thusquestionably valid assistance),
this definition may catch programs which use NULL incorrectly (e.g. when the
ASCII NUL character was really intended; see question 5.9).
Question 5.17
Seriously, have any actual machines really used nonzero null pointers, or
different representations for pointers to different types?
The Prime 50 series used segment 07777, offset 0 for the null pointer, at
least for PL/I. Later models used segment 0, offset 0
for null pointers in C, necessitating new instructions such as TCNP (Test C
Null Pointer), evidently as a sop to all the extant
poorly-written C code which made incorrect assumptions. Older,
word-addressed Prime machines were also notorious for
requiring larger byte pointers (char *'s) than word pointers (int *'s).
The Eclipse MV series from Data General has three architecturally supported
pointer formats (word, byte, and bit pointers),
two of which are used by C compilers: byte pointers for char * and void *,
and word pointers for everything else.
Some Honeywell-Bull mainframes use the bit pattern 06000 for (internal) null
pointers.
The CDC Cyber 180 Series has 48-bit pointers consisting of a ring, segment,
and offset. Most users (in ring 11) have null
pointers of 0xB00000000000. It was common on old CDC ones-complement
machines to use an all-one-bits word as a
special flag for all kinds of data, including invalid addresses.
The old HP 3000 series uses a different addressing scheme for byte addresses
than for word addresses; like several of the
machines above it therefore uses different representations for char * and
void * pointers than for other pointers.
The Symbolics Lisp Machine, a tagged architecture, does not even have
conventional numeric pointers; it uses the pair <NIL,
0> (basically a nonexistent <object, offset> handle) as a C null pointer.
***************************************************************
Depending on the ``memory model'' in use, 8086-family processors (PC
compatibles) may use 16-bit data pointers and 32-bit function pointers, or
vice versa.
***************************************************************
***************************************************************
Some 64-bit Cray machines represent int * in the lower 48 bits of a word;
char * additionally uses the upper 16 bits to indicate a byte address within
a word.
***************************************************************
References: K&R1 Sec. A14.4 p. 211
Ivan Molella

alcun effetto. 
Forse vuoi dire : che possono non avere effetto ...
;)


c'è tra un char e un long.
La differenza che c'e' tra char e long non influenza affatto la
dimensione dei puntatori. Io sto parlando del tipo "puntatore-a-T".


!= (void far *),anche se questa e' un eccezione di piattaforma.
ma la dimensione di tutti i puntatori far e' la stessa e la dimensione
di tutti i puntatori near e' la stessa, cosi' come e' la stessa la
dimensione di tutti i puntatori in modalita' protetta.


 pointer a carattere era di 64.
Non mi č chiara una cosa: questa differenza c'č proprio a livello
macchina o l'hai riscontrata in un particolare compilatore? La presenza
a livello di istruzioni macchina significherebbe che l'accesso ad una
parola di memoria puň essere fatto solo in un spazio di indirizzamento
ridotto (un po' come i segmenti dell'MS-DOS) mentre quello ad un singolo
byte puň coprire uno spazio piů ampio. Questo mi sembrerebbe strano e
non ne capirei la logica. La capisco invece nel caso dei puntatori a
funzione dato che probabilmente il codice ed i dati potrebbero essere
posti in zone diverse di memoria con dimensioni diverse.
EMG

 Secondo le FAQ di Steve Summit sembrerebbe propio di si.
Perň ho notato alcune cose che vorrei evidenziare:
1. Si parla quasi sempre di rappresentazione interna diversa e non di
dimensioni diverse.
2. L'eccezione č proprio quella di cui parlava Maurizio e pare
riguardare solo i char * e i void *.
3. Le considerazioni riportate sembrano riguardare in generale computer
molto vecchi.
4. L'unico riferimento dato č al K&R1 che, notoriamente, non rappresenta
piů il C attuale.
EMG

 ;)
Oops! Sorry.
EMG

 Io sto parlando del tipo "puntatore-a-T".
Ma puntatore-a-T non è "un" tipo. E' una famiglia di tipi al variare di
T. O pensi che, ad esempio, i tipi int *, long * e char ** siano lo
stesso tipo?
EMG

 dimensione di tutti i puntatori in modalita' protetta.
Anch'io la penso cosě ma evidentemente esistono o sono esistite delle
eccezioni (il Cray citato da Maurizio).
EMG

T.
E difatti il discorso sulla dimensione vale per l'intera famiglia.


 E difatti il discorso sulla dimensione vale per l'intera famiglia.
Quindi tu sei sicuro che tutti i puntatori-a-T debbano essere, a norma
di standard, della stessa dimensione? Anche io penso sia cosě ma vorrei
averne conferma ufficiale.
EMG

 più il C attuale.
Non per questo cosi' antico da non dover essere piu' preso in considerazione
Ivan Molella

 posti in zone diverse di memoria con dimensioni diverse.
Mi sembra di ricordare che la differenza sia proprio a livello macchina
perchè tutte le word sono allineate in modo particolare, lo spazio di
indirizzamento dovrebbe essere lo stesso.
.... però è un vago ricordo, l'avevo studiato l'anno scorso....
e cmq non ho mai fisicamente messo una mano su un cray....
--
________________________________
Togliete NoSpaM per rispondermi
bye Brain

 Non per questo cosi' antico da non dover essere piu' preso in considerazione
Ma se la cosa fosse stata riportata anche sulla seconda edizione
immagino avrebbero messo il riferimento a quella. La sua assenza mi fa
pensare che le cose siano cambiate. Tutto qui.
EMG

 fissa.
Sicuro? E come faccio a conoscere la dimensione del tipo "puntatore"?
--
Alessandro Monti