Newsgroup: it.comp.lang.c
Titolo: Help non capisco l'errore

Scusate e da poco che sto imparando il c.
Compilando il seguente programma riscontro i seguenti errori nella procedura
riempimondo che non riesco a capire, potete aiutarmi?
1) Pointer to structure required on left side of -> or ->*
2) Parameter 'mondo' is never used
#include <stdio.h>
#define MAX 50
typedef struct
 {
  int x,y,z;
  int xp,yp;
 } punto;
punto mondo[MAX];
void riempimondo(punto *mondo)
{
 int i,corx,cory,corz;
 for (i=0; i < MAX; ++i)
  {
   printf(" Inserisci il valore della x:\t");
   scanf("%d\n",corx);
   mondo[i]-> x = corx;
   printf(" Inserisci il valore della y:\t");
   scanf("%d\n",cory);
   mondo[i] -> y = cory;
   printf(" Inserisci il valore della z:\t");
   scanf("%d\n\n",corz);
   mondo[i]-> z = corz;
  }
}
void visualizzamondo(punto *mondo);
int main (void)
{
 riempimondo(&mondo);
 visualizzamondo(&mondo);
}

 }
Scrivi:
 riempimondo(mondo);
 visualizzamondo(mondo);
mondo e' gia' il puntatore al vettore che hai definito come:
punto mondo[MAX];
Ciao.
-- 
     (ZZZ)       Filippo Salotti, Bagni di Lucca, Lucca, Italy.
    //   \\  _                 E-mail : 
fil...@humnet.unipi.it
   /Y\    ZD<_o===============================================o
 .oZZZZZo.     | Studente Ingegneria Informatica Automatica  |
<OXXXXXXXO>    | Dip. Sistemi Elettrici Universita' di Pisa. |

Ferioli Mirko (
feriol...@tin.it
) wrote:
[ snip ]
: potete aiutarmi?
#include <stdio.h>
#define MAX 5
typedef struct {
        int x, y, z;
} punto;
punto mondo[MAX];
void riempimondo(punto * mondo)
{
        int i, answer;
        for (i = 0; i < MAX; ++i) {
                printf("Inserisci il valore della x: ");
                scanf(" %d", &answer); mondo[i].x = answer;
                printf("Inserisci il valore della y: ");
                scanf(" %d", &answer); mondo[i].y = answer;
                printf("Inserisci il valore della z: ");
                scanf(" %d", &answer); mondo[i].z = answer;
        }
}
void visualizzamondo(punto * mondo)
{
        int i;
        for (i = 0; i < MAX; ++i)
                printf("%02d: %6d %6d %6d\n", i+1, mondo[i].x,
                        mondo[i].y, mondo[i].z);
}
int main(void)
{
        riempimondo(mondo);
        visualizzamondo(mondo);
        return 0;
}
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

 visualizzamondo(&mondo);
mondo è un array e quindi quando viene passato come parametro ad una
funzione 'decade' nel puntatore al suo primo elemento. Pertanto non devi
estrarne l'indirizzo. Scrivi
riempimondo(mondo);
visualizzamondo(mondo);
Inoltre manca
return 0;
alla fine della funzione main().
EMG

}
Vedi sopra : devi utilizzare 'riempimondo(mondo)' e 'visualizzamondo(mondo)' in
quanto con 'mondo' stai gia' passando un indirizzo.
Pero' vorrei darti un consiglio : dato che 'mondo' e' il nome dell'array e che
dal punto in cui e' dichiarato in poi e' sempre visibile (anche all'interno
delle funzioni), dichiaralo come 
punto mio_mondo[MAX]; 
e passalo alle funzioni con
 riempimondo(mio_mondo);
 visualizzamondo(mio_mondo);
Il consiglio, cioe', e' quello di utilizzare per una variabile globale un nome
diverso da quello usato per il parametro locale di una funzione.
Questo potrebbe evitare errori difficili da individuare.
Andrea, mica uno qualunque...
--------------------------------------------------
"Ho cambiato signature, si vede ?" (Anonimo)
--
Posted from 
itaca.ulysse.it
 [195.223.254.1]
via Mailgate.ORG Server - 
http://www.mailgate.org

estrarne l'indirizzo. Scrivi
"Decade" ?
Io direi che il nome 'mondo' e' comunque un puntatore all'inizio del blocco di
memoria dove sono conservati gli elementi dell'array e pertanto come tale viene
passato.
In C nulla "decade" in quanto non esiste il passaggio per riferimento (come in
Pascal) ma solo per valore.


Pascal) ma solo per valore.
Questo c'entra poco.  Considera il seguente ulteriore esempio:
    const char* pippo(const char* const* ppc) {
        return *ppc;
    }
Dato un opportuno puntatore, ad esempio:
    const char* ciccio = "Ciccio";
la chiamata "pippo(&ciccio)" e` corretta e deve funzionare; invece,
dato un array (che NON e` un puntatore!):
    const char paperoga[] = "Paperoga";
la chiamata "pippo(&paperoga)" NON e` corretta e un compilatore
C standard _deve_ segnalarla come errore.  Il modo piu` semplice
e generale di spiegare il perche` e`: l'operando di &, come quello
di sizeof, NON e` soggetto ad alcuna promozione o conversione
("non decade" e` un modo conciso benche` non altrettanto chiaro
di dire la stessa cosa).  Alcuni compilatori preferiscono invece
diagnosticarlo come un problema di lvalue vs rvalue, ma la spiegazione
"qui non decade" si applica uniformemente ai vari casi in cui appunto
un nome-di-array NON decade a puntatore-al-primo-elemento
(sizeof, connessione fra extern, uso dell'operatore &, ...), e quindi
e` preferibile per ragioni di "rasoio di Occam".
Alex

Questo potrebbe evitare errori difficili da individuare.
Ottima idea.  Quando poi e` possibile evitare del tutto le variabili
globali (e spesso lo e`), questa e` un'idea ancora migliore, e per
la stessa ragione.
Alex

 Pascal) ma solo per valore.
Appunto. Se esistesse il passaggio per riferimento non ci sarebbe alcuna
conversione implicita ma si utilizzerebbe (come in C++) il tipo
riferimento_a T.
EMG

applicabili al C vi sono l'uso di sizeof, e la connessione fra extern).
Le differenza tra un array e un puntatore le conosco benissimo.
Io non parlo dell'array ma del "nome" dell'array e sono due cose ben diverse.
Inoltre, in questo thread si sta parlando di C, non di C++.
L'esempio di sizeof non e' accettabile in quanto esso e' un operatore unario,
non una funzione del C.
Andrea, mica uno qualunque...
--------------------------------------------------
"Ho cambiato signature, si vede ?" 
--


a che vedere con il puntatore al suo primo elemento.
Un array non e' un tipo di dato.
Questo puo' essere vero in C++, ma non in C.
Nel C non e' neanche menzionato come tipo di dato.
L'array e' un costrutto, non una categoria primitiva.
Se gli esperti del newsgroup pensano questo, rimangano pure esperti del
newsgroup, ma non dicano troppo in giro di essere esperti di C.


occorre che la funzione qualcosa prenda il tipo giusto, cioe` punto**).
Certo, perche' parli di un array di puntatori, non di un array semplice.
Che fai, stravolgi le cose ?
Prova a scrivere
punto indirizzo[...];
qualcosa(&indirizzo);
Con il prototipo "void qualcosa ( punto array[] );"
Che e' lo stesso caso del programma di sopra.
Ti ripeto che il nome di un array e' una costante, mentre un puntatore e' una
variabile.


variabile.
Anche un puntatore puo` essere una costante, ovviamente:
    char* const pco = "ciao!";
Adesso pco e` una costante, ma non per questo puo` essere
equiparato ad un array come:
    char arr[] = "ciao!";
In particolare, l'espressione &pco ha tipo X dato da:
    char* const* X
mentre l'espressione &arr ha tipo Y dato da:
    char* (*Y)[6]
Questi due tipi X e Y non decadono l'uno all'altro, quindi
(con un compilatore corretto e rigoroso) non possono a
norma di standard essere usati in modo intercambiabile
(eccetto che, come qualsiasi altro puntatore, per un
parametro formale di tipo void*).
Alex

newsgroup, ma non dicano troppo in giro di essere esperti di C.
Uno che non sa neppure cosa e` un tipo di dato nel linguaggio C,
eppure pretende di valutare la MIA esperienza sul tema...?!  Guarda
che sbagli gruppo: it.reticiviche.bologna.barzellette e` l'unico gruppo
su cui potresti postare roba del genere...
Alex

non una funzione del C.
Anche & (indirizzo-di) e` un operatore unario; e allora?  Se X e` un
array, &X (quello che tu hai scritto "non ha senso") e sizeof(X) sono
due esempi di contesti, in cui, applicando un operatore unario del
linguaggio al NOME dell'array, usare questo nome NON equivale a
usare l'indirizzo del primo elemento dell'array stesso.
Sciorinami poi l'esempio seguente, compilando e linkando
questi file sorgenti C:
:: pippo.c
#include <stdio.h>
/* dichiarazioni corrette */
extern char *const pext1;
extern char aext1[];
/* dichiarazioni errate (scambiate) */
extern char *const aext2;
extern char pext2[];
void lavora(int come) {
    switch(come) {
    case 0: printf("%s\n", pext1); break;
    case 1: printf("%s\n", aext1); break;
    case 2: printf("%s\n", pext2); break;
    case 3: printf("%s\n", aext2); break;
    }
}
:: fine del file pippo.c
:: pluto.c
extern void lavora(int);
/* dichiarazioni corrette */
char *const pext1 = "pext1";
char aext1[] = "aext1";
/* dichiarazioni errate (scambiate) */
char aext2[] = "aext2";
char *const pext2 = "pext2";
int main()
{
    int op;
    for(;;) {
        printf("Opzione, 0-3; <0|>3, exit: ");
        if(!scanf("%d",&op)) break;
        if(op<0 || op>3) break;
        lavora(op);
    }
    return 0;
}
:: fine del file pluto.c
Facci ora il piacere di spiegare, in termini della tua
"visione del mondo" (e del linguaggio C), i comportamenti
di questo programma C.  Dal punto di vista di chi considera
che un puntatore (anche const!) e un array sono cose ben
diverse, anche se il nome del secondo, in tanti contesti, puo`
decadere al primo, non ci sono naturalmente problemi
(nota che anche la corrispondenza nel link e` per nome,
solo che, naturalmente, e` un contesto in cui non decade).
Alex

usare l'indirizzo del primo elemento dell'array stesso.
Perche' sizeof ha valore SOLO a tempo di compilazione e nel passare un nome di
un array agisce sul nome in quanto "identificatore" restituendo la dimensione
totale basandosi sul tipo di dichiarazione !
Non e' affatto comparabile con una funzione che accetti come parametro il nome
di un array e quindi un indirizzo.
Posso ammettere che la scrittura &X decada in X ma non viceversa (come vorresti
far credere).


su cui potresti postare roba del genere...
Bologna ?! nooo troppo lontano ! e poi non credi che farei meglio a spedire le
tue risposte ? :)


ho teste` citato, o affermazioni irrilevanti come questa
Non direi che sono affermazioni irrilevanti, e darei loro, invece, parecchia
importanza...
Ma sei libero di fare come ti va...
Facciamo cosi', io continuero' a consigliare i newbie secondo cio' che so e che
e' corretto, tu continua a parlare di decadenza e poi vediamo chi dei due
ottiene i risultati migliori.
Addio, statti bene...


tue risposte ? :)
Non ti pare che la tua affermazione "un array non e` un tipo di
dato" meritasse SOLO di essere postata su di un gruppo di
barzellette?  Pensi che sia in qualsiasi modo difendibile?  Non ti
pare che, portando simili erronee e ridicole affermazioni in una
discussione su temi difficili, danneggi la possibilita` di condurre
decentemente la discussione stessa?!  Se devi postare scemenze
come quella, fallo su di un gruppo riservato alle barzellette.
Le mie risposte non contenevano alcuna assurdita` paragonabile
alla tua asserzione "Un array non e` un tipo di dato".
Alex

Ippopapero Acquatico (andrea_...@CHITIHACHIESTONIENTEbigfoot.com) wrote:
[ snip ]
: Il nome di un array e' un puntatore costante al suo primo elemento 
: e lo e' sempre, non decade mai !
Dal KR, 2° edizione (in italiano), Appendice A "Reference Manual", 
A7.1 "Generazione di puntatori", pag. 260:
"Se il tipo di un'espressione o di una sottoespressione e'
 'vettore di T', per un certo tipo T, allora il valore della
 espressione e' un puntatore al primo elemento del vettore, ed
 il suo tipo viene alterato in 'puntatore a T'."
<INCISO>
	Ora viene il bello ;)
</INCISO>
"Questa conversione non ha luogo se l'espressione e' l'operando
 dell'operatore unario &, o di ++, -- o sizeof, oppure se e' 
 l'operando sinistro di un operatore di assegnamento o dello
 operatore .(accesso ad un membro di una struttura).[...]"
[ snip ]
: Perche' sizeof ha valore SOLO a tempo di compilazione e nel 
: passare un nome di un array agisce sul nome in quanto 
: "identificatore" restituendo la dimensione totale basandosi 
: sul tipo di dichiarazione !
Guarda che stai ammettendo che il nome dell'array, in contesti diversi,
viene valutato in maniera diversa ;)
: Non e' affatto comparabile con una funzione che accetti come 
: parametro il nome di un array e quindi un indirizzo.
Sempre dal KR, Appendice A, A10.1 Definizione di funzioni, pag. 299:
"[...]Se il tipo di un parametro e' dichiarato 'vettore di tipo', la
 dichiarazione e' letta come 'puntatore a tipo';[...]"
Ciao ciao


ottiene i risultati migliori.
Bisognera` che, tutte le volte che dovro` segnalare ai newbie le
molte cose errate che scrivi (come di recente un ptr.membro dove
ptr era un puntatore, roba davvero grave), la segnalazione sia
accompagnata da un puntatore a questo thread, cosi` da aiutare
i newbie a distinguere chi il linguaggio C lo conosce (e ci sa anche
ragionare sopra) e chi continua ad affastellare affermazioni false,
a volte ammettendolo piu` tardi e a volte no ma senza scusarsene,
e ostinazione vera.  Se poi, con questi dati sotto mano, vorranno
scegliere di seguire i tuoi errori, invece di interessarsi al linguaggio
C come esso e` effettivamente definito, beh, "chi e` causa del
suo mal..."!-)
Alex

far credere).
Diciamo "come vorrebbero fare credere un certo Kernighan
e un dato Ritchie", visto che, essendo evidentemente del
tutto incapace di ragionare con la tua testa, accetti soltanto
"argomenti per autorita`" -- e ti sei fregato con le tue mani
citando a ripetizione un passaggio discorsivo di K&R, quindi
implicitamente riconoscendo la loro autorita`.
Strofinarti intensamente il becco in quei brani che Foco ha
citato dall'appendice del K&R non sara` altrettanto
soddisfacente come strofinartelo in quella robaccia che
hai cosi` testardamente postato, ma non c'e` male.
Adesso continua a farci divertire, caro pagliaccio, cercando
di spiegarci questa ultima, suprema, meravigliosa perla
"che la scrittura &X decada in X" -- sei sprecato su di un
palcoscenico ristretto come questo gruppo, dovresti darti
decisamente al cinema comico, ci sei proprio portato!
Con quali produzioni sintattiche proporresti di sostituire
l'attuale grammatica formale del C per dare la benche`
minima parvenza di senso compiuto alla tua veramente
deliziosa frasetta teste` citata...?
Grazie ancora per le sonore, incredibili risate che susciti,
Alex

     char* (*Y)[6]
Qui invece mi perdo: l'indirizzo di un array non dovrebbe essere un
puntatore all'array stesso? Y invece sembra essere un puntatore ad un
array di 6 puntatori a carattere. Ma probabilmente mi sto confondendo
io. Puoi spiegarmi?
EMG

 (array di char terminati da 0 binario),
Scusa, non ricordo una cosa: il valore '\0' è _sempre_ zero binario
oppure (come nel caso del puntatore nullo) non è dato sapere quale
configurazione di bits lo esprimerà in una particolare implementazione?
EMG

 Adesso continua a farci divertire, caro pagliaccio,
Non ti lasciar andare. Cerca di mantenere la discussione su di un piano
impersonale. Le idee che esprimi sono vere o false (valida la prima per
me) indipendentemente dagli interlocutori coinvolti.
EMG

...

Certo, cosi` come sono vere o false del tutto indipendentemente
da quale sia la mia opinione su questi interlocutori, o del fatto che
io la esprima o meno.  E allora, nei casi estremi, particolarmente
con "interlocutori" che si sono permessi di _deridere_ la verita`
(ti ricordi certe uscite dell'ippopapero...?), mi tolgo la soddisfazione
di sbeffeggiarli, perche` no?
Alex

io. Puoi spiegarmi?
No, non posso spiegare per la semplice ragione che mi e`
sfuggito un asterisco di troppo; leggasi, esattamente come
tu dici,
        char (*Y)[6]
cioe` appunto puntatore-ad-array-di-sei-caratteri.  Sorry.
E` bello (e non scherzo!!!) sapere che quel che si posta su
questo gruppo viene accuratamente scrutinato, e gli errori
scemi vengono evidenziati: magari fossero cosi` precise le
code inspection che si praticano "nella realta`"!-)
Alex

configurazione di bits lo esprimerà in una particolare implementazione?
Buona domanda.  _Credo_, ma NON ne sono sicuro, che debba
essere tutti-i-bit-a-zero; e` difficile pensare a un programma C
compliant, anche non strictly, che possa determinare se '\0' ha
qualche bit non-zero su di una particolare implementazione, visto
che in pratica qualsiasi 'operazione su char' lo trasforma invece
in un int (e _deve_ trasformarsi in un int 0, con tutti i bit a 0, su questo
non ci piove).  Forse si potrebbe fare una union fra un array di
tali caratteri e un int, ma, si sa, accedere a un membro di una
union quando l'ultimo membro di quella union che e` stato settato
non e` quello, gia` di per se, basta a rompere la compliance del
programma.
La situazione e` diversa per il puntatore nullo perche` castare
un puntatore a intero e` compliant (anche se non strictly)...
Alex

 in questo caso; non stanno invece fra quelli che NON si possono usare?
Ehm, ma che cavolo ho scritto? Non ci fare caso. Cancella ++ e -- dalla
lista delle eccezioni...
EMG

Salve
Scusate se rompo.
Ho il seguente problema.
Qui di seguito ho inserito le procedure che utilizzo per gestire la lista.
Il problema è il seguente ,ho notato che riesco al massimo allocare 4210
tessere.
Una volta allocate tutte le tessere devo visualizzarle e fin qui tutto bene.
Il problema e' che una volta visualizzate chiamo la procedura Cancella_Torre
e rinserisco 4210 tessere e qui succede di tutto,
o il programma temina o compaiono numeri sballati a video.
Sapete aiutarmi ?
Grazie
___________________________________________________
#include "torre.h"
int prova = 0;
extern int Dep3[MAX][MAX][MAX][MAX];
torre pila;
void Inizializza_Torre(torre *stk)
{
 stk -> cnt = 0;
 stk -> top = NULL;
}
void Inserisci_nella_Torre(int x, int y, int z, int k,torre *stk)
{
 tessera *p;
 int error;
 p = malloc(sizeof(tessera));
 if(p != NULL)
 {
  p -> a = x;
  p -> b = y;
  p -> c = z;
  p -> d = k;
  p -> succ = stk -> top;
  stk -> top = p;
  stk -> cnt++;
  printf("\n allocati %d",++prova);
 }
 else
  {
   printf("\n !!! E R R O R E   I R R E V E R S I B I L E !!!");
   printf("\n Memoria insufficiente il programma viene terminato ");
   do
    {
     printf("\n Premere il tasto 1 per terminare\t");
     error = -1;
     scanf("%d",&error);
     fflush(stdin);
    }while (error != 1);
    exit(-1);
  }
}
void Stampa_Lista(tessera *stk)
   {
    if (stk == NULL)
     printf(" NULL\n ");
    else
    {
     printf("%d%d%d%d\t",stk -> a,stk -> b,stk -> c,stk -> d);
     Stampa_Lista(stk -> succ);
    }
  }
void Visualizza_Torre (torre *stk)
{
 tessera *primo;
 if ( stk -> top == NULL)
  printf("La torre e' vuota\n");
 else
  {
   printf("\n");
   primo = stk -> top;
   Stampa_Lista(primo);
   fflush(stdout);
  }
}
void Cancella_Torre(torre *stk)
{
 tessera *p;
 while (stk -> top != NULL)
 {
  p = stk -> top;
  stk -> top = stk -> top -> succ;
  stk -> cnt--;
  printf("\ncontatore %d",stk ->cnt);
  free(p);
  --prova;
 }
}
_______________________________________________
Ho allegato anche le strutture.
struct elemento
 {
  int a,b,c,d;
  struct elemento *succ;
 };
typedef struct elemento tessera;
struct stack
 {
  int cnt;
  tessera *top;
 };
typedef struct stack torre;