[C] dubbio sulle struct

_overflow_1
Mentre programmavo un po' mi è venuto un dubbio, vi posto il codice per farvi capire a cosa mi riferisco:


#include <stdio.h>

struct ele{
    char a[20];
};

void prova(struct ele *);

int main()
{
    struct ele p;

    prova(&p);

    return 0;

}

void prova(struct ele *p)
{
    scanf("%s", &p->a);

    printf("%s", p->a);

}


#include <stdio.h>

struct ele{
    char a[20];
};

void prova(struct ele *);

int main()
{
    struct ele p;

    prova(&p);

    return 0;

}

void prova(struct ele *p)
{
    scanf("%s", p->a);

    printf("%s", p->a);

}


Perché questi due codici funzionano entrambi? Voglio dire perché funziona sia con la & che senza (mi riferisco alla scanf nella funzione prova)?
Io sarei propenso ad usare la scanf senza la & quindi
scanf("%s", p->a);
dato che sto trattando le stringhe in questo caso (cosa diversa sarebbe ad esempio se il campo a della struct fosse di tipo int), se non fosse che la prof (sbagliando?) ha detto che la & va messa.

Ringrazio tutti anticipatamente.

Risposte
hamming_burst
Ciao,
ma hai provato a compilarlo?

se usi "gcc" usa il parametro
 gcc -Wall


se ancora non capisci il problema, ne riparliamo volentieri :-)

indovina
nei miei esempi viene sempre riportato 'SENZA' &.
Ora però tu hai detto che entrambi 'funzionano', li hai gia compilati?

_overflow_1
già compilati e funzionano entrambi... A dire il vero io il dubbio neanche lo avrei se non fosse stato per la professoressa che mi ha detto che la & ci vuole.

hamming_burst
che compilatore usi?

comunque ti spiego perchè con & è sbagliato.

scanf, vuole come secondo parametro un puntatore.

te dai come parametro: &p->a.

p = struct*

p è un puntatore, ad un altro puntatore (la stringa).

p->a è quello che si dice zucchero sintattico, è l'equivalente di, (*p).a
essendo "a" un puntatore, (*p).a è anchesso un puntatore, in questo caso ad una stringa (char*).

&p->a = &((*p).a), cioè l'indirizzo della cella di memoria che punta al puntatore, non al contenuto.

perciò non sarà un char*, ma un char**. ok?

_overflow_1
Si si infatti è quello che penso io.
Ma dato che la professoressa mi ha detto il contrario di quello che pensavo mi è venuto un dubbio.

Come compilatore uso MinGW, strano comunque che non mi dia errore nel secondo caso, non mi da errore neanche a runtime.

Grazie mille.

Rggb1
Non deve dare errore di compilazione: il tipo passato a scanf() è corretto.

Domanda: C o C++?

_overflow_1
Ok, ma neanche a run-time
C

hamming_burst
#Rggb:
a me da due warning, con gcc -Wall.

Ska1
un array di char non è identificato tramite il puntatore alla cella del primo elemento? A me è stato spiegato così e quindi è ragionevole quel comportamento :)

Provate:
char a[20];
printf("%d\n", a == &(a[0])); // Stampa 1, ovvero valore vero :)

hamming_burst
uuuh che pirla, c'avete ragione.
Ritiro quello che ho scritto, sorry.

Per il warning, basta fare un casting di tipo.

Rggb1
@ham_burst
Ma guarda che le tue osservazioni erano corrette, ma mi torna che funzioni in entrambi i casi. Solo che non capivo perché il docente insistesse con 'mettici & davanti'... boh.

hamming_burst
rileggendo sono corrette fino ad un certo punto, con l'osservazione di Ska, con "==" mi ha fatto capire/ricordare che l'ultima frase è quella sbagliata.

a == &(a[0])

a == &(*a)

così si capisce che sono la stessa cosa. La struct mi aveva un attimo fatto dubitare dell'indirizzo che risulta con l'applicazione di &.

perciò sarà sempre (char*) e non (char**).
Sono quelle cose del C che non sopporto molto, anche se sono utili in certi casi, ma avere costrutti differenti per dire la medesima cosa, fan commettere errori.

Grazie Rggb :-)

_overflow_1
Ma quindi in buona sostanza, è giusto quello che dico? e qualcuno può dirmi perché in entrambe i casi i codici funzionano?

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.