Newsgroup: it.comp.lang.c
Titolo: Problema filosofico-pratico :)

ciao a tutti,
c'e' un problema su cui mi arrovello da qualche tempo ;)
supponiamo che devo fare un programmino che faccia elaborazione dati,
i dati sono contenuti in un array "numbers" monodimensionale. Metto
solo i prototipi e il main()...
-----------------------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#define DIM 20
int numbers[DIM];
void readnumbers(int *ptr_numbers);
// Questa funzione memorizza negli elementi di "numbers" i valori
numerici immessi da tastiera
void visualizenumbers(int *ptr_numbers);
// Questa funzione mostra a video (in un 2o momento) i valori numerici
contenuti in "numbers"
float estimateAvg(int *ptr_numbers);
// Questa funzione stima la media dei valori contenuti in
"numbers" (vabbe' giusto come esempio ;) )
-----------------------------------------------------------------------------------------------------------------------------------------------
int main()
{
 readnumbers(numbers);
 visualizenumbers(numbers);
 printf("\nLa media dei numeri immessi da tastiera e':
%f",estimateAvg(numbers));
 while (!getchar()=='\n');
}
-----------------------------------------------------------------------------------------------------------------------------------------------
ora, usando la define rendo le funzioni dipendenti da tale
dichiarazione!
L'alternativa sarebbe la seguente: ( ho un parametro formale in piu'
per ogni funzione...):
void readnumbers(int *ptr_numbers, int DIM);
void visualizenumbers(int *ptr_numbers, int DIM);
float estimateAvg(int *ptr_numbers, int DIM);
cioe' in pratica i cicli for dentro alle 3 funzioni sfruttano il
valore di DIM indicato come parametro formale.
Lo scopo che vorrei raggiungere e' di rendere le funzioni
"riutilizzabili" in qualche modo.
Mi piacerebbe riuscire a togliere il parametro formale DIM dalle
funzioni "visualizenumbers" e "estimateAvg".
Come posso fare?
Mi piacerebbe sfruttare sizeof(numbers)/sizeof(int), ma ovviamente non
è possibile, dato che sizeof agisce a tempo di compilazione... :(
grazie x l'aiuto,
Paolo.

 è possibile, dato che sizeof agisce a tempo di compilazione... :(
Tra l'altro, se provi a dusare sizeof sul parametro non ottieni quello 
che ti aspetti perche' si tratta di un puntatore a int quindi avra' 
dimensioni di un puntatore, non dell'array a cui sta puntando.
ciao
Giacomo

 parametro, quindi devi fornirlo tu come ulteriore parametro.
Giacomo il motivo per cui volevo eliminare DIM dalle funzioni
visualizenumbers() e estimateAvg() e' che mi sembra ridondante dover
specificare DIM pure li' (è un problema "filosofico", come accennato
nel subject del messaggio)!
cioe' ormai l'ho creato l'array numbers (con readnumbers), le
dimensioni sono note (a tempo di esecuzione), mi piacerebbe poter
evitare di dover utilizzare DIM
come parametro formale anche per le ultime 2 funzioni!
P.S. ma e' vero che "una funzione può restituire un qualsiasi tipo di
dati TRANNE UN ARRAY", come dice Schildt sul manuale di C/C++?
grazie mille,
Paolo.

 ultra-standard il tipo di DIM dovresti metterlo size_t e non int)
domandina: ma size_t vuol dire unsigned int, vero?
sembra di si, leggendo lo standard ISO/IEC 9899:TC2!
P.S. tornando al discorso del perche' volevo evitare di usare il DIM
in tutte e 3 le funzioni, il motivo pratico e' che sono costretto nel
codice a specificare il valore di DIM per le 3 funzioni... ma come
faccio se non so a priori la dimensione dell'array da trattare!?!
grazie mille,
Paolo.

sembra di si, leggendo lo standard ISO/IEC 9899:TC2!
In realtà, non dovresti chiedertelo e non fare affidamento su un tipo
specifico sottostante. Quei tipi nascono apposta per astrarre.

 faccio se non so a priori la dimensione dell'array da trattare!?!
I casi sono questi:
1 - conosci a compile time DIM, e allora è giusto metterlo in una 
costante globale;
2 - DIM viene scelto in runtime, ma tutti gli array hanno la stessa 
dimensione. Allora DIM potrebbe essere una variabile globale, e non 
servirebbe passarlo alle funzioni;
3 - ci possono essere contemporaneamente array con diverse DIM. Allora è 
necessario attaccare questa informazione ad ogni array e quindi le tue 
funzioni devono accettare DIM come parametro.
E.


[...]
Sono nel caso 2, ho deciso di usare queste 4 funzioni:
size_t readDim();
void readnumbers(int *ptr_numbers, size_t DIM);
void visualizenumbers(int *ptr_numbers, size_t DIM);
float estimateAvg(int *ptr_numbers, size_t DIM);
la prima delle 4 chiede all'utente di specificare DIM...
in questo modo sono costretto ad usare DIM in ogni funzione, pero' da'
l'idea di qualcosa di riutilizzabile!
grazie mille,
Paolo.

 sizeof operator".
Penso che "integer" non sia un sinonimo di "int", in questo contesto, ma 
che voglia dire uno qualunque dei tipi interi, ovvero: long int, int, 
short int o char (mi pare che anche char sia un tipo intero).
E.

 Certo, e' piu' comodo scrivere "size_t" che "unsigned int" ;)
Bada che "integer type" non significa "int type".
Non è detto che size_t sia grande quanto un int.
Lo standard parla chiaro e dice che è grande quanto il tipo restituito da
sizeof. Più che di comodità, si tratta di correttezza logica.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 sizeof. Più che di comodità, si tratta di correttezza logica.
il discorso e' chiaro... cmq sul mio pc si prende 4 byte, come
l'unsigned int.
(Il tutto e' partito dal fatto che Giacomo mi ha detto "per essere
ultra-standard il tipo di DIM dovresti metterlo size_t e non int ")
grazie a tutti,
Paolo.

 ultra-standard il tipo di DIM dovresti metterlo size_t e non int ")
Giacomo ha ragione.


Ciao a tutti,
per quello che ho letto in giro, si usa sizeof per rendere il codice
portabile, evitando di fare assunzioni sulla dimensione degli interi.
Ora pero' io NON sto facendo nessuna assunzione, semplicemente
dichiaro DIM (che ricordo, serve nel mio caso a memorizzare il numero
di elementi di un array) di un tipo come unsigned int,e quanto poi
occupera' occupera'.
In altre parole non mi sembrava scontato, come invece ha detto
Giacomo, che sia ultra-standard utilizzare size_t per memorizzare DIM.
Posso utilizzare altrettanto correttamente una variabile unsigned int
(che come size_t variera' la sua dimensione in base alla macchina
ospite, questo e' evidente!).
saluti,
Paolo.

 Posso utilizzare altrettanto correttamente una variabile unsigned int
No. Non è altrettanto corretto.


Ciao a tutti,
allora ricordo che il programmino aveva queste 3 funzioni,
void readnumbers(int *ptr_numbers, int DIM);
void visualizenumbers(int *ptr_numbers, int DIM);
float estimateAvg(int *ptr_numbers, int DIM);
e che avevo dichiarato
int numbers[DIM];
Giacomo mi suggeriva di usare size_t al posto di int nei 3 prototipi.
Faccio notare che non ho mai fatto uso di sizeof nel programma in
questione.
Sembrerebbe quasi da quello che dici, Andrea, che in un buon programma
non si dovrebbero usare gli int ma sempre i size_t!?! forse ho capito
male!
grazie mille,
Paolo.

Ciao a tutti,
quello che volevo dire (e poi chiudo davvero su questa questione,
promesso! ;-D ) e' che non vedo differenze significative tra scrivere:
void readnumbers(int *ptr_numbers, int DIM);
void visualizenumbers(int *ptr_numbers, int DIM);
float estimateAvg(int *ptr_numbers, int DIM);
e scrivere invece:
void readnumbers(int *ptr_numbers, size_t DIM);
void visualizenumbers(int *ptr_numbers, size_t DIM);
float estimateAvg(int *ptr_numbers, size_t DIM);
giacche', ripeto, non ho mai MAI fatto uso di sizeof nel codice!
in entrambi i casi, per quel poco che leggo, la dimensione della
variabile DIM variera' in base alla macchina. Se invece mi sbaglio e
la cosa non sta cosi', sarei portato a concludere che in un buon
programma non bisogna mai e poi mai usare i tipi come int ecc ecc, e
che bisogna sempre al posto loro sfruttare size_t. Fiuuuu ;D
grazie mille x il supporto,
Paolo.

 male!
Hai capito male. Bisogna usare size_t quando si specifica una dimensione.
Non vuol dire nulla il fatto di non usare mai sizeof.
La lunghezza di una stringa, per esempio, č memorizzabile come size_t:
size_t len = strlen("pippo");


 giacche', ripeto, non ho mai MAI fatto uso di sizeof nel codice!
Non vuol dire nulla. E le differenze non le vuoi vedere perché sei
cocciuto e ostinato. Se io scrivo: 
int a[n];
è corretto che io usi un size_t per muovermi da 0 a n-1.
Se io scrivessi, nel caso più banale:
char a[n];
la lunghezza n sarebbe rappresentabile con un size_t e quindi anche
l'indice dovrebbe avere tipo size_t.
Gli interi vanno bene quando c'è bisogno degli interi.


 size_t len = strlen("pippo");
mi pare che size_t (il cui ruolo non e' per niente messo in evidenza
nel libro che sto leggendo, vero che non l'ho ancora finito...) ha
un'importanza strategica in C, nonostante il fatto che non e' uno dei
tipi predefiniti!
grazie mille,
Paolo.

 Come posso fare?
L'alternativa è quella di usare dei valori sentinella alla stregua delle
stringhe ASCIIZ:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
        char *last_name;         
        char *first_name;
} node_t, *pnode_t;
char *dupstr(const char *s) {
     char *r=malloc(strlen(s)+1);
     if (r)
       strcpy(r, s);    
     return r;
}
pnode_t node_new(const char *firstn, const char *lastn) {
        pnode_t i = malloc(sizeof *i);
        if (i) {
           i->first_name = dupstr(firstn);
           i->last_name = dupstr(lastn);
        }
        return i;
}
void node_print(pnode_t self) {
     printf("%s %sn", self->first_name, self->last_name);
}
int main(int argc, char *argv[])
{
    size_t i;
    pnode_t *p = malloc(4*sizeof **p);
    p[0] = node_new("mario", "rossi");
    p[1] = node_new("guido", "bianchi");
    p[2] = node_new("antonio", "verdi");
    p[3] = 0; /* valore sentinella */
    for (i=0; p[i]; i++) {
       node_print(p[i]); 
    }    
    return 0;


 #include <stdlib.h>
[...]
mmm grazie Andrea, ci do uno sguardo, vediamo se fa al caso mio!
grazie mille,
Paolo.

Ciao a tutti,
per quello che ho letto in giro, si usa sizeof per rendere il codice
portabile, evitando di fare assunzioni sulla dimensione degli interi.
Ora pero' io NON sto facendo nessuna assunzione, semplicemente
dichiaro DIM (che ricordo, serve nel mio caso a memorizzare il numero
di elementi di un array) di un tipo come unsigned int,e quanto poi
occupera' occupera'.
In altre parole non mi sembrava scontato, come invece ha detto
Giacomo, che sia ultra-standard utilizzare size_t per memorizzare DIM.
Posso utilizzare altrettanto correttamente una variabile unsigned int


Scusate l'ultimo messaggio e' evidentemente da "cassare", Andrea ha
chiarito perfettamente l'uso di size_t!
Ciao e grazie a tutti!
Paolo.

 No. Non è altrettanto corretto.
Capisco che in questo caso è più sensato utilizzare size_t. Però direi 
che il codice
#include ...
#define DIM 4096
int array[DIM];
void fillArray(int *array, int dim) {
   int i;
   for (i=0;i<dim;++i) array[i]=i;
}
int main(int argc, char *argv[]) {
   int count;
   if (argc==2) {
     count=atoi(argv[1]);
     if (count>0 && count<DIM)
	fillArray(array,count);
   }
}
è del tutto corretto e portabile. Sostanzialmente è questo che Iranon78 
stava facendo.
E.

stava facendo.
E' inutile, non ci si intende.

 E' inutile, non ci si intende.
ciao Andrea, per quanto mi riguarda mi hai chiarito il ruolo di
size_t, probabilmente se invece di un vecchio Schildt pre-TC2 mi
trovassi in casa un buon libro di programmazione non avrei chiesto
niente sul size_t (non si tratta di essere cocciuti, semplice
inioranzia, pero' studiando e leggendo si rimedia subito ;-D )
ho un dubbio: sul libro citato prima si dice che "le parentesi quadre
VUOTE indicano che l'array è di lunghezza non determinata".
Ora nel programmino che ho introdotto all'inizio del topic, ho usato
alla fine un int numbers[] e il compilatore mi da' un warning:
"[Warning] array 'numbers' assumed to have one element "
quindi il comportamento del compilatore, in questo caso, sembrerebbe
di cautelarsi dando all'array numbers[] dimensione 1. Cioe' se non ho
capito male, in fase di compilazione, il gcc (mingw) alloca spazio in
memoria per poter salvare un solo elemento di tipo int, o sbaglio?
grazie mille,
Paolo.

 "[Warning] array 'numbers' assumed to have one element "
Credo sia una estensione del gcc. Gli array senza dimensioni non sono
ammessi, anche perché dopo non avresti modo di impostargliene una, non
essendo gli array dei puntatori.


 essendo gli array dei puntatori.
ehm un attimo pero' e' un warning, compila tranquillamente!?!
P.S. qualcuno mi da' idee su come posso costruire una funzione
ricorsiva per il calcolo del fattoriale che avvisi se ho superato il
limite massimo ammesso dagli int? (o long int o quello che volete)
P.P.S. qual è lo specificatore di formato da usare in printf con un
unsigned long int? e con un unsigned long long int?
grazie mille,
Paolo.

 unsigned long int? e con un unsigned long long int?
http://www.google.it/search?hl=it&q=man+printf&btnG=Cerca+con+Google&meta=


 limits.h)  diviso il valore fino a quel punto calcolato.
A proposito di questo, mi chiedo se le CPU moderne hanno ancora i FLAG 
quali: carrier, overflow etc... Se sě, non c'č modo di accedervi dal C? 
Ci sono situazioni in cui ho dovuto "sprecare" dei bit solamente per 
avere un controllo sugli overflow o sui resti.
E.

 avere un controllo sugli overflow o sui resti.
I flags ci sono esattamente come nei vecchi 8086 ma non c'è modo di 
accedervi direttamente da C.  Se sei in grado di inserire codice 
assembler in linea nei tuoi programmi ci sono istruzioni speciali per 
caricarle in un registro.
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

Se sě, non c'č modo di accedervi dal C? 
Tramite l'assembly built-in che molti compilatori (gcc compreso) mettono a
disposizione. Alle brutte scrivi del codice con un assembler e lo linki.
Ma perché vuoi farlo?


 Ma perché vuoi farlo?
No, infatti non voglio farlo, se non è possibile usare il C standard. 
Però sarebbe utile. Ad esempio se vuoi definire la somma su interi con 
un numero arbitrario di bit potresti sommare 32 bit alla volta e 
sfruttare il flag per il riporto.
E.

sfruttare il flag per il riporto.
Be', di librerie per l'aritmetica in precisione multipla ce ne sono
già un bel po', in giro...

 
OK,  quindi deduco che tu nei tuoi programmi per dichiarare un array  di 
5  elementi usi qualcosa del tipo:
char a[(size_t) 5];
:-)
Giorgio

char a[(size_t) 5];
No, ma uso un size_t, come si conviene, come indice per scorrere
l'array. Consiglio anche a te di guardare di che tipo è il risultato
di strlen().