Azzerare array

valentina921
Salve a tutti,
ho un dubbio banale: per azzerare (in C) un array multidimensionale basta fare semplicemente in dichiarazione:

int array[10][10] = {0}

come nel caso unidimensionale, oppure è per forza necessario il doppio ciclo for?

Grazie in anticipo

Valentina

Risposte
hamming_burst
"valentina92":
per azzerare (in C) un array multidimensionale basta fare semplicemente in dichiarazione:

int array[10][10] = {0}

certo che si può fare, ovviamente funziona con qualsiasi numero per inizializzare in un colpo l'array :-)
se hai dubbi basta che fai una print sugli elementi.

valentina921
L'ho fatto, ma per alcune posizioni dell'array mi stampa numeri strani, mentre per tutti gli altri 0! per questo mi era venuto il dubbio! il mio era un array[100][100] e l'ho azzerato in quel modo là, ma mi dava questo strano risultato..

hamming_burst
"valentina92":
L'ho fatto, ma per alcune posizioni dell'array mi stampa numeri strani, mentre per tutti gli altri 0! per questo mi era venuto il dubbio! il mio era un array[100][100] e l'ho azzerato in quel modo là, ma mi dava questo strano risultato..

mmm mi faresti vedere il pezzo di codice di stampa e dichiarazione...

valentina921
Certo, eccolo:


#include
#include
#include


int chicchi (int, int);

main () {
double campo[99][99]={0};
int i, j;

for (i=0; i<100; i++) {
for (j=0; j<100; j++) {
printf ("\n campo[%d][%d]=%d", i, j, campo[j]);
}
}
}

valentina921
il pezzo prima del main mi sono scordata di toglierlo, era una funzione che ho fatto dopo!

hamming_burst
uuuh quanti errori, piccoli ma fonti di bug inimmaginabili...

Prima cosa sono andato a controllare, ricordavo male una cosa.
Per inizializzare un array multidimensionale bisogna usare una sintassi di questo tipo:
int a[100][100]={{0],{0}};

per ogni dimensione dell'array. Scusa pensavo che a più dimensioni fosse uguale...

per il resto ti faccio notare alcuni errori:

  double campo[99][99]={0};

hai detto che è un array di dimensione $100$ perciò devi dichiararlo di $100$ non $99$. L'iterazione è $[0,99]$ che sono $100$ celle.
Seconda è una array di double, perciò dichiara esplicitamente il tipo che utilizzi nell'inizializzazione. Perciò:
  double campo[100][100]={{0.0},{0.0}};


  printf ("\n campo[%d][%d]=%d", i, j, campo[i][j]);

il tipo da stampare è double (%lf) non un decimal (%d) Perciò:
  printf ("\n campo[%d][%d]=%lf", i, j, campo[i][j]);


così dovrebbe essere ok. :-)

Ultima cosa che compilatore od IDE utilizzi? Mi pare che non sia possibile non dichiarare il tipo di ritorno del
main()

ma dovrebbe essere:
int main()
o nel vecchio standard
void main()


EDIT:
vedere correzioni di apatriarca nei post seguenti.

apatriarca
Allora, vediamo di mettere un po' di chiarezza sugli standard del C. L'attuale standard del C è del 2011, ma credo che nessun compilatore abbia un supporto minimamente decente.. Quello che l'ha preceduto è del 1999 ed è stato molto sfortunato, con praticamente nessun compilatore che lo supporta completamente e molti che non lo supportano affatto. Lo standard più famoso e supportato è quello del 1989, il primo standard del C. In nessuno di questi standard è ammessa una scrittura del tipo
void main()

e prima di tali standard, la parola chiave void era tutt'altro che diffusa. Era un'estensione supportata da alcuni compilatori. Ma quando non si volevano restituire risultati, semplicemente non si scriveva il valore di ritorno e il compilatore lo interpretava come int. Quindi
main()

era permesso e diffuso nello standard del 1989 e nei codici precedenti ed era del tutto equivalente a
int main()

Nei nuovi standard non è più permesso in quanto int non è più considerato il tipo di ritorno di default.

Esistono alcuni compilatori che permettono void come valore di ritorno del main, ma è un'estensione del linguaggio e non è un comportanto standard. Alcuni compilatori richiedono poi che il tipo di ritorno sia void, ma si tratta di compilatori per sistemi particolari, molto distanti dai sistemi mainstream a cui siamo abituato e in praticamente tutti non esiste un sistema operativo al quale tornare e il programma non viene in pratica mai terminato (non si esce insomma mai dal main in questi sistemi).

Per gli standard più recenti sono ammesse solo le seguenti versioni di main (o equivalenti):
int main(void)
int main(int argc, int **argv)


Per quanto riguarda l'inizializzazione degli array il discorso è un po' più complicato. Se l'array ha "static storage duration" (esiste insomma per tutta la durata dell'applicazione) e non viene inizializzato, allora è automaticamente inizializzato con tutti zero. Se viene inizializzato solo in parte, allora il resto viene inizializzato come nel caso precedente con tutti zero. Per cui la riga
int a[3] = {1};

inizializza l'array con {1, 0, 0}.
Per cui tutti i codici che avete scritto in pratica dovrebbero funzionare per azzerare l'array.

hamming_burst
molto interessante, grazie apatriarca dei chiarimenti.
devo dire di aver ricordato male e pensavo che void main() fosse una vecchia versione non più accettata.
"apatriarca":

int main()

Nei nuovi standard non è più permesso in quanto int non è più considerato il tipo di ritorno di default.
...
Per gli standard più recenti sono ammesse solo le seguenti versioni di main (o equivalenti):
int main(void)
int main(int argc, int **argv)


c'è una svista penso qua :-)
Comunque sono andato a vedere il nuovo standard ISO/IEC 9899:2011, hai ragione :)


Per quanto riguarda l'inizializzazione degli array il discorso è un po' più complicato. Se l'array ha "static storage duration" (esiste insomma per tutta la durata dell'applicazione) e non viene inizializzato, allora è automaticamente inizializzato con tutti zero.

intendi l'inizializzione garantita dal selettore BSS (standard ELF) ?

apatriarca
No, non c'è una svista. Semplicemente non mi riferivo alla riga subito precedente ma a main() senza int. Nei nuovi standard non è più permessa la dichiarazione di una funzione senza specificare il tipo di ritorno.

Con static storage duration intendo semplicemente riferirmi a variabili che sono globali o specificate come static all'interno di una funzione e che quindi esistono per tutta la durata dell'esecuzione del programma. Che siano specificati nel selettore BSS nello standard ELF non ha niente a che fare con lo standard C. Lo standard C non è legato neanche lontanamente a ELF. Nei casi che ho specificato, lo standard C afferma che, se la variabile non è inizializzata, allora è inizializzata con "zero" (l'equivalente di zero nei vari tipi). Per azzerare quindi un array globale o dichiarato come statico all'interno di una funzione non è necessario scrivere codice. Se invece la variabile è locale, se non è inizializzata, può avere qualsiasi valore.

Il secondo discorso sulla inizializzazione riguarda invece l'inizializzazione di un array con i numeri tra le parentesi graffe. Se il numero di valori inseriti è inferiore a quello degli elementi dell'array, gli altri sono inizializzati a zero. Per cui si ha il comportamento che ho descritto sopra.

hamming_burst
"apatriarca":
No, non c'è una svista. Semplicemente non mi riferivo alla riga subito precedente ma a main() senza int. Nei nuovi standard non è più permessa la dichiarazione di una funzione senza specificare il tipo di ritorno.

ah ok, così ha più senso.


Con static storage duration intendo semplicemente riferirmi a variabili che sono globali o specificate come static all'interno di una funzione e che quindi esistono per tutta la durata dell'esecuzione del programma. Che siano specificati nel selettore BSS nello standard ELF non ha niente a che fare con lo standard C. Lo standard C non è legato neanche lontanamente a ELF. Nei casi che ho specificato, lo standard C afferma che, se la variabile non è inizializzata, allora è inizializzata con "zero" (l'equivalente di zero nei vari tipi). Per azzerare quindi un array globale o dichiarato come statico all'interno di una funzione non è necessario scrivere codice. Se invece la variabile è locale, se non è inizializzata, può avere qualsiasi valore.

Sì certo sono standard diversi. Ma più mi riferivo al comportamento ("semantico"), le variabili inserite nel segmento BSS sono garantite essere inizializzate, ma hai ragione a differenziare.

valentina921
Ok, ho corretto %d con %f sul printf e l'array viene azzerato anche con il codice che avevo scritto io, quindi vale come nel caso unidimensionale? Perchè questo array non è statico, subirà delle modifiche nel corso del programma, quindi non viene inizializzato automaticamente a 0...e quindi, mettendo campo[100][100]={0} non ho dato 0 solo alla prima posizione, ma a tutte, no?
Poi, forse il C che ci hanno insegnato è la versione precedente, perchè si usa scrivere:

main ()

senza il tipo davanti.

apatriarca
Sì, come ho detto il C89 è ancora il più diffuso nonostante siano passati più di 10 anni da quando è stato sostituito con un nuovo standard. Per cui è abbastanza normale che ti sia stato insegnato quello standard del C. Sinceramente credo comunque che in questo caso, aggiungere i 4 caratteri per scrivere int e uno spazio, non sia un grosso sforzo e si rende il codice più compatibile con le nuove versione del C e con il C++.

Credo che tu abbia frainteso il significato di statico. Non significa che è costante, solo che esiste e può essere usato per tutta la durata del programma. Era giusto parlarne perché in questo caso, come ho detto, l'azzeramento dell'array è automatico. Negli altri casi invece è necessario inizializzare l'array, ma se lo si vuole azzerare è sufficiente scrivere in pratica {} o {0}, in quanto, in presenza di una lista incompleta di valori, il resto viene azzerato. Per cui campo[100][100] = {0} azzera tutte le posizioni come anche campo[100][100] = {} o campo[100][100] = {0,0,0} o ...

valentina921
Capito, adesso è tutto chiaro. Grazie mille!

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