Newsgroup: it.comp.lang.c
Titolo: Curiosità. Il C viene spiegato bene ?

Il C sembra un linguaggio che riserva sorprese anche a chi lo utilizza 
da anni.
Che sia colpa di libri troppo pratici e poco astratti?
Chi studia Matematica sa che l'iper-semplificazione rende le cose molto 
più difficili di quanto non lo siano in realtà.
Oggi ho parlato con un mio collega che sosteneva che il C fosse 
"contorto" e ho scoperto che in realtà aveva una piccola lacuna (colmata 
in 5 min. d'orologio).
Per es. assumete che la variabile 'ptr' sia un puntatore a un array di 
32 puntatori a un array di 20 puntatori a un puntatore a una funzione 
che restituisce un puntatore a un unsigned e riceve due interi signed.
Quanti sanno scrivermi la dichiarazione in un unico statement (quindi 
senza typedef o altri espedienti)?
Ho notato che molti hanno problemi con questo genere di cose, quando in 
realtà sono semplicissime se solo si conosce il metodo.
Kiuhnm

 
Io pure. Se hai tempo perdi 5 minuti di orologio anche con me.
Grazie.

 unsigned int (*(*(*ptr)[32])[20](int, int));
Quasi, ma c'è qualche errore. Per es. hai spostato la parentesi alla 
fine e così il compilatore associa (int, int) all'array!
Il metodo che uso è molto semplice e rivela anche una cosa "strana" del 
linguaggio C (o del compilatore che uso :) ).
Facciamo finta che qualcuno abbia già dichiarato ptr per noi e di 
doverlo semplicemente usare per chiamare una delle funzioni:
puntatore
(*ptr)
a un array
(*ptr)[0]
di puntatori
*(*ptr)[0]
a un array
(*(*ptr)[0])[0]
di puntatori
*(*(*ptr)[0])[0]
a un puntatore
**(*(*ptr)[0])[0]
a una funzione che prende due int in input
(**(*(*ptr)[0])[0])(int, int)
e restituisce un puntatore
*(**(*(*ptr)[0])[0])(int, int)
a un unsigned
unsigned *(**(*(*ptr)[0])[0])(int, int)
Nota che prima di aggiungere elementi a destra racchiudo l'espressione 
già presente tra tonde (ma probabilmente conosci già la regola 
destra-sinistra).
Ora sostituiamo i due zeri con le dimensioni degli array:
unsigned *(**(*(*ptr)[32])[20])(int, int)
Es:
unsigned *(**(*(*ptr)[32])[20])(int, int);
unsigned *ok = (*(*(*ptr)[1])[2])(1, 2);
o, se preferisci,
unsigned *ok = (*********************(*(*ptr)[1])[2])(1, 2);
che dà lo stesso risultato!
Quello che si nota è che nella dichiarazione dobbiamo usare un asterisco 
per indicare il puntatore alla funzione, mentre nell'utilizzare ptr 
possiamo omettere l'asterisco. Aggiungere più asterischi non sembra 
alterare il funzionamento del programma!
Un'altra cosa. Solitamente in C si punta a un array puntando al primo 
elemento dell'array. In realtà questo non sarebbe puntare all'array, ma, 
appunto, a un elemento dell'array.
Ecco perché, ma vedo che non è il tuo caso, alcuni hanno difficoltà a 
comprendere i puntatori agli array.
Per es. le ultime due righe del codice seguente sono equivalenti:
---
int a, b;
int k[5] = {1,2,3,4,5};
int (*p)[5];
int *p2;
p = &k;
p2 = k;
a = (*p)[4];
b = p2[4];
---
Però non capisco il C(/C++) quando non accetta
*p = k;
A rigor di logica, dovrebbe trattare gli array come oggetti e copiare il 
contenuto di k in *p. Direi che è una piccola pecca.
Kiuhnm

 ---
Che puzza d'aglio incravattato. Divertente, ma temo che tu lo debba 
proporre su it.comp.lang.c++

Kiuhnm wrote:

Si tratta solo di seghe mentali

 il contenuto di k in *p. Direi che è una piccola pecca.
Pecca?!?!
p è un puntatore ad un array di 5 interi; k è un array di 5 interi
*p equivale a p[0]
k equivale &k[0]
risultato finale: p[0] = &k[0];
stai assegnando al primo elemento di p, l'indirizzo del primo elemento 
di k; ci credo che non copia il contenuto di k in *p.

 k equivale &k[0]
Quest'ultima riga afferma che k, un array, è uguale al puntatore al 
primo elemento di un array quindi un array, in C, non è un oggetto, ma 
un puntatore costante, il che è appunto bizzarro.
Non sarebbe molto lontano dal vero dire che, praticamente, gli array in 
C non esistono.
Kiuhnm

Kiuhnm wrote:

Ed infatti  è così!
Il C considera gli array in modo diverso da altri linguaggi. Ed è giusto.

 C non esistono.
Esistono però sono tipi senza operazioni. Utilizzano operazioni sui
puntatori.
-- 
Horst

 senza typedef o altri espedienti)?
In realta' se uno ha bisogno di una dichiarazione del genere dovrebbe 
essere anche in grado di scriverla e se poi ha dei dubbi puo' sempre 
usare un programma automatico come cdecl per verificarla.
Pero' queste "dichiarazioni terroristiche"  servono piu' a fare 
impressione sui newbies che altro. Statisticamente, non sono 
necessariamente pane quotidiano. La domanda interessante per me sarebbe, 
all' interno di un contesto comprensibile, se e' davvero necessaria una 
struttura dati di questo tipo o se non ci sono modi per semplificare.
Giorgio

 puntatori.
Mi pare che sia questione di punti di vista. Ovviamente tanto vale 
seguire il punto di vista di chi l'ha ideato, ma la sostanza non cambia, 
IMHO.
Kiuhnm