Newsgroup: it.comp.lang.c
Titolo: Array e puntatori: qui qualcosa non va.

Ciao, vorrei sommare due array, elemento per elemento e mettere il risultato
in un terzo array, elemento per elemento, solo che il seg. codice non
funziona e mannaggia la stanchezza (sono andato a dormire alla 4.00 e mi
sono svegliato alle 7.30) non riesco a capire il perchè.
Non è che mi date una mano?
#include <stdio.h>
#define SIZE 10
void somma_array(int primo[], int secondo[]);
int main()
{
      int a[SIZE]={1,1,1,1,1,1,1,1,1,1};
      int b[SIZE]={9,8,7,6,5,4,3,2,1,0};
      somma_array(a,b);
      system("PAUSE");
      return 0;
}
void somma_array(int primo[], int secondo[])
{
   int totale[SIZE];
   int *p_totale=&totale[0];
   int contatore=0;
   for(contatore=0; contatore<SIZE; contatore++)
   {
      totale[contatore]=primo[contatore]+secondo[contatore];
      printf("%d + %d = %d\n", primo[contatore], secondo[contatore],
totale);
   }
}
Il compilatore è il DevC++. Già che ci siamo...ma perchè devo creare un
puntatore all'array totale[SIZE]? Non basta quella riga poco più sotto a
riempirlo?
(non funziona).
Grazie a tutti e BUON NATALE.


Talking about music is like dancing about architecture.
                -- Laurie Anderson

 quale totale vuoi stampare ??? totale[contatore] !!!
Ciao, infatti nel testo dell'esercizio del libero deve esserci qualche
errore. Infatti il testo recita:
"Scrivere una funzione somma_array( ) che accetti due array della stessa
dimensione , sommi ciascun elemento di un array con quello corrispondente
dell'altro array e ponga i risultati in un terzo array."
La soluzione è quella riportata sopra, ma ottengo dei valori strani:
1 + 9 = 37813920
1 + 8 = 37813920
1 + 7 = 37813920
1 + 6 = 37813920
1 + 5 = 37813920
1 + 4 = 37813920
1 + 3 = 37813920
1 + 2 = 37813920
1 + 1 = 37813920
1 + 0 = 37813920
Premere un tasto per continuare . . .
Dunque è incasinata la soluzione, vero?

 quale totale vuoi stampare ??? totale[contatore] !!!
Infatti mettendo totale[contatore] raggiungo lo scopo....ma che casino hanno
fatto nel testo?? :)
Grazie mille cmq.

 puntatore all'array totale[SIZE]?
Infatti così non serve a niente, come non serve l'inizializzazione di
contatore.
Avresti potuto sostituire l'istruzione di somma con:
    *p_totale++ =primo[contatore]+secondo[contatore];
che dovrebbe essere più veloce ed efficiente.
Maurizio.

 che dovrebbe essere piů veloce ed efficiente.
Questa sintassi me la segno, non la sapevo. *p_totale++ incrementa l'indice
dell'array, vero? *p_totale++= totale[contatore]++

 }
Io la scriverei cosi`:
void somma_array(int primo[], int secondo[]) {
	int totale[SIZE];
	int c;
	for (c = 0; c < SIZE; c++) {
		totale[c] = primo[c] + secondo[c];
		printf("%d + %d = %d\n", primo[c], secondo[c], totale[c];
	}
}
Il puntatore non serviva a nulla,  e nella printf dimenticavi che totale
era  un array  (in pratica  passavi un  puntatore). Dovresti provare  ad
abilitare tutti gli warning sul  tuo compilatore. Il gcc, ad esempio, mi
dice "warning: int format, pointer arg (arg 4)" sulla printf.
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Dicono che  il cane sia  il miglior  amico dell'uomo. Secondo me  non e`
vero. Quanti dei vostri amici avete fatto castrare, recentemente?

 l'indice dell'array, vero? *p_totale++= totale[contatore]++
Noooo.
Prima cosa: totale[] è un array e non è un puntatore; sono quasi la stessa
cosa, ma l'array è un puntatore costante e non può essere incrementato.
Forse volevi dire totale[contatore++]; in questo caso viene incrementato
l'indice (contatore). L'effetto è lo stesso ma si raggiunge in modo diverso.
p_totale è un puntatore all'array e cioè una variabile che contiene
l'indirizzo dell'array. Con *p_totale viene puntato il primo elemento
dell'array; il ++ incrementa il puntatore che andrà a puntare all'elemento
successivo. contatore non viene toccato.
Maurizio.

 l'indice dell'array, vero? *p_totale++= totale[contatore]++
Noooo.


 che dovrebbe essere più veloce ed efficiente.
assolutamente no. Qualunque compilatore appena decente e' in grado di 
ottimizzare in casi come questo; le righe:
        totale[contatore] = primo[contatore] + secondo[contatore];
e
        *p_totale++ =primo[contatore]+secondo[contatore];
molto probabilmente produrranno lo stesso identico codice, con 
l'inconveniente che la seconda e' molto meno leggibile.
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 l'inconveniente che la seconda e' molto meno leggibile.
Se tu avessi detto che il guadagno in termini di efficienza e velocità erano
minimi potevo anche essere d'accordo, ma così cosa posso rispondere se non
di andare a guardare il codice che viene prodotto? Hai mai provato a
disassemblare il codice?
Come faranno i compilatori a produrre lo stesso codice quando sono diverse
le variabili utilizzate?
Maurizio.

le variabili utilizzate?
Perche' sono fatti bene e ci lavorano ormai da diversi anni (pensa al
GCC da quanti hanni lo sviluppano, figurati se ormai non sono stati in
grado di implementare un buon ottimizzatore di codice).
Nota: e' indifferente il nome che dai tu alle variabili, non verra'
certamente usato quello e potrebbe capitare che per 2 variabili che tu
hai indicato come separate venga usata la stessa etichetta (ti
assicuro che implementare una cosa del genere e' facilissima, e puo'
essere facco facilmente riutilizzando un algoritmo per la colorazione
dei nodi di un grafo).
In ogni compilatore, anche quelli che si fanno per gioco per imparare
a scriverli, c'e' un componente chiamato ottimizzatore che si occupa
appunto di prendere il tuo codice e di tradurlo in istruzioni
efficienti.
In genere pero' ti viene lasciata la facolta di scegliere quando vuoi
che il codice (ASM, poi da ASM a linguaggio macchina c'e' una
traduzione 1:1) risultante sia ottimizzato.
Anche se non specifichi nessun livello di ottimizzazione il
compilatore cambia alcune tue istruzioni C con altre piu' efficaci (io
ero convinto del contrario, ma invece e' cosi').
Per nozioni piu' dettagliate guarda i manuali dei compilatori (non
quello che ti spiega come compilare, ma quello che ti spiega le scelte
implementative).
Mox :)

 come separate venga usata la stessa etichetta
Cosa c'entra l'etichetta? Dopo la compilazione, una variabile è solo una o
più locazioni di memoria e al suo nome viene sostituito il suo indirizzo. Se
uso un puntatore, l'indirizzo usato è uno solo: il microprocessore carica in
un registro il suo indirizzo e basta. Se uso un array con un indice, prima
il microprocessore deve leggere da una locazione di memoria l'indice
(contatore o come altro è chiamato), lo deve moltiplicare per il numero di
bytes occupati da ogni elemento dell'array, lo caricano in un registro e
infine ci sommano l'indirizzo del primo elemento dell'array. Mi sembra che
di lavoro ce ne sia un po' di più, anche se con i processori superpotenti
che abbiamo si riesce a fare tutto con un paio di istruzioni assembler (i
vecchi microprocessori ne richiedevano parecchie di più).
Comunque ho verificato e il codice generato è diverso. Questo è il codice
che viene generato utilizzando un puntatore:
    mov eax,[ebp-034h]; px
quest'altro, invece per un array:
    mov eax,[ebp-02ch]; counter
    mov eax,dword ptr [ebp+eax*04h-028h]
Poi se della differenza non riesce a rendersene conto nessuno, nemmeno con
un orologio di precisione, è un altro discorso.
Maurizio.

 successivo. contatore non viene toccato.
Infatti. Grazie mille.

che viene generato utilizzando un puntatore:
E' perfettamente possibile... ci sono tanti compilatori e tanti modi
di ottimizzare. Dovresti postare anche compilatore utilizzato e
livello di ottimizzazione che hai indicato al compilatore. Ovvio che
non te lo sei inventato, ma da compilatore a compilatore, da livello
di ottimizzazione a livello di ottimizzazione, cambiano radicalmente i
risultati.
Detto come lo dici tu sembra che i compilatori traducano in modo
fedele dal C all'ASM... se la traduzione e' fedele come mai non riesci
a tornare indietro, ma puoi solo disassemblare?
Questo e' dovuto all'ottimizzatore che altera il tuo codice rendendone
impossibile un lavoro di traduzione inversa.
Mox

 a tornare indietro, ma puoi solo disassemblare?
Per prima cosa nell'eseguibile non ci sono i nomi delle variabili e delle
funzioni. Che interesse potrebbe avere un "decompilato" con i numeri al
posto dei nomi? Poi ci sono, come non ho disconosciuto, codici equivalenti.
Ma questo non sarebbe una difficoltà: basta scrivere uno dei tanti codici. A
parte questo ritengo che il motivo più importante è che forse non interessa
nessuno, vista la complessità di un decompilatore. Insomma il gioco non vale
la candela.
In passato ho molto lavorato con l'assembler. Disassemblatori in giro ce ne
sono tanti eppure un disassemblato non è mai la stessa cosa del sorgente. E
se questo vale per l'assembler figuriamoci per il C.
Maurizio.