NGI.Home > Forum
  EOLO HOME  OFFERTE INTERNET WIRELESS EOLO  FORMULA ADSL
   
   
WEBMAIL
   
 
  > Register  
  > FAQ  
  > Members List  
 
  > Calendar  
  > Today's Posts  
   
 

Go Back   NGI Forum > Tech & Tech > Developer's Zone

Reply
 
Thread Tools Rate Thread
Old 3rd December 2010, 11:37   #1
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,290
[Impariamo il C] Lezione 3

Buongiorno.

Prosegue il corso collaborativo di programmazione.

Riassunto delle puntate precedenti:
  1. installazione dell'IDE, cenni di architettura degli elaboratori
  2. sintassi del C, programmazione strutturata
In questo capitolo:
  • ulteriore analisi dell'Hello World e sintassi
  • introduzione dei tipi di dato e alle variabili


Ancora sintassi del C

Ancora una volta, prendiamo il nosto hello world, che non smette di far discutere! .

Code:
void main()
{
  printf("Hello World!\n");
  system("pause");
}
Ormai sappiamo cosa significa la prima riga (è la dichiarazione del corpo principale), sappiamo perché ci sono le graffe a delimitare il corpo e sappiamo istruzioni vanno terminate col punto e virgole.

Vediamo le istruzioni. A guardarle con attenzione, hanno la stessa "forma":

nome_della_funzione ( parametri... )

i parametri delle due funzioni, in questo caso, sono delle strighe, ovvero una sequenza di caratteri delimitata da doppi apici (quelli sopra il 2, per intenderci). Le funzioni sono un aspetto assai complesso della programmazione (ed esistono linguaggi, detti appunto funzionali, che hanno SOLO funzioni e niente altro, come LISP, Scheme, Haskell, ecc.) e le tratteremo nella prossima lezione.

Naturalmente, non esistono solo le stringhe come possibili parametri delle funzioni (=istruzioni, userò questi termini come sinonimi). Vediamo quali tipo di dato esistono in C.


I tipi di dato e le variabili

Ecco un riassunto dei tipi di dato esistenti in C. Tra parentesi indico il modo cui ci si riferisce nella programmazione C ad ogni tipo di dato:


Numerici

Interi (int)
Numeri reali a virgola mobile (float)
Numeri reali a virgola fissa ma doppia precisione (double)

Ricordiamo dalla prima lezione di architettura che nella CPU i dati sono rappresentati da gruppi di bit. Interi e numeri a virgola mobile utilizzano una intera word (quindi, generalmente, 32 bit), i double (come si può intuire dal nome) usano due word (e quindi il doppio dei bit).

Naturalmente, essendo il numero di bit finito, non possiamo rappresentare qualsiasi numero: saranno limitati. Quali numeri possiamo rappresentare? Per determinarlo, facciamo un brevissimo excursus sulla rappresentazione binaria dei numeri interi (senza virgola). Se prendiamo in esame un byte, esso sarà formato da 8 bit. Es.:



Come si vede, ogni bit in una certa posizione corrisponde ad un valore chiamato "peso", pari a due elevato alla posizione (partendo da 0). Questo significa che il numero binario 01101001 in decimale vale la somma dei soli pesi dei bits a 1 quindi:

64 + 32 + 8 + 1 = 105

(non conto 128, 16, 4 e 2 perché sono a zero). I numeri interi (int) funzionano così. In realtà, non è così vero perché l'ultimo bit a sinistra (quello più "pesante", che per questo viene chiamato bit più significativo o MSB) viene usato per il segno.

Quindi, se teoricamente con un byte posso rappresentare tutti i numeri da 0 ( 00000000 ) a 255 ( 11111111 ), dedicando l'MSB al segno il range cambia in -128 a 127. Con un intero senza segno posso arrivare fino a 2^32*.

La rappresentazione in memoria dei float e double è molto più complessa e non verrà trattata; per informazioni riguardo i range di valori assumibili ad numeri float e double, vi rimando a questo link.

Per tutti i valori numerici è possibile dire al C di non riservare un bit per il segno, basta apporre la parola unsigned davanti al tipo di dato.


Per dovere di precisione, esistono anche altre versioni ristrette o potenziate come precisione (short e long), ma non li tratteremo in questo corso.


* curiosità: è anche il numero di indirizzi IP disponibili sul pianeta secondo il protocollo IPv4. Riuscite a dedurre il perché?


Alfanumerici
Singolo carattere (char)

I caratteri, come detto nella lezione introduttiva, occupano esattamente un byte*.

* se ve lo state chiedendo, la risposta è sì: anche i caratteri hanno un segno .


Altri tipi fondamentali


Nulla (void)
Enumerazione esplicita (enum)

L'enumerazione esplicita ci consente di creare una lista di costanti. La vedremo in dettaglio più avanti.


Perché sono importanti i tipi di dato, dovreste già averlo intuito: in base ai calcoli che vogliamo effettuare, dovremo maneggiare diversi tipi di dato con diverse caratteristiche. Questi dati, ricordando sempre l'architettura di Von Neumann, devono stare nella memoria, dunque dobbiamo istruire il computer su come organizzarla.

Inoltre, le nostre funzioni, come abbiamo anticipato, accettano dei valori in ingresso e producono dei valori in uscita (perfino il main!), dunque dobbiamo dire al compilatore "ehi amico, aspettati in ingresso un carattere e un double, e restituiscimi un intero".


La domanda a questo punto potrebbe essere: va bene, ma come carichiamo in memoria dei valori? la risposta sono le variabili.

In sostanza, la memoria principale del nostro computer è organizzata in blocchi nei quali possiamo riversare i nostri dati e alterarli (tramite la CPU). Noi possiamo dire "voglio un blocco tutto per me che si chiami antani e che possa contenere un numero intero". Ecco come avviene la magia in C:

Code:
int antani;
Fine! Il nome della variabile è del tutto libero, ma non si possono usare spazi e caratteri riservati. Limitatevi a lettere e numeri.

Ecco finalmente spiegato cosa significavano quelle parole arcane scritte in verde, e iniziamo a capire perché nel main ho preferito scrivere void.


Per assegnare un valore ad una variabile è sufficiente utilizzare l'operatore di assegnamento "=". Ad esempio, se volessi creare una variabile di tipo virgola mobile che contiene il pigreco dovrei scrivere:

Code:
float pigreco;
pigreco = 3.14159;
nulla di più semplice. Ricordate sempre: PRIMA si dichiara una variabile e poi si usa, perché sennò il compilatore non sa dove andare a mettere quel valore nella memoria!


Ultima cosa sulle variabili (per ora, avete notato che non abbiamo visto le stringhe come tipo di dato?): non si usano solo con valori arbitrari. Possiamo utilizzare nell'assegnamento anche altre variabili.


Esercizio 1: quanto vale b dopo l'esecuzione di questo codice?

Code:
int a;
int b;
a = 1;
b = a;
Esercizio 2: sapendo che la stampa di un numero intero in C si fa così:

Code:
int variabile;
printf ("%d \n", variabile);
scrivere un codice che dichiara tre variabili intere, le assegna ai valori 1, 2, 3 e le stampa a video tutte e tre.

Un bonus per chi dichiara le variabili senza segno.
__________________
Lode a Bacco, in saecula saeculorum.
Emergent

Last edited by Arësius; 3rd December 2010 at 17:44.
Arësius is offline   Reply With Quote
Old 3rd December 2010, 12:08   #2
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,867
io ho fatto così:

Spoiler:
Code:
#include <stdio.h>
#include <stdlib.h>
void main()
{
     unsigned int a;
     unsigned int b;
     unsigned int antani;
     a=1;
     b=a;
     antani=a+b;
     printf ("%d - %d - %d \n", a, b, antani);
     system("pause");
}


però sono andato un attimo a memoria per voler visualizzare tutti e 3 i dati sulla stessa riga diciamo...perché in realtà non hai spiegato come farlo.
da totale ignorante sarei stato costretto ad usare 3 volte il printf();

una cosetta che probabilmente è OT:
non ho capito la parte dei numerici.
Cosa sono i numeri in virgola mobile e fissa?
e specialmente cosa vuol dire questo esempio:
Quote:
Come si vede, ad ogni bit corrisponde un valore (indicato come "peso" nell'immagine quì sopra). Questo significa che il numero binario 01101001 nella notazione decimale vale la somma dei pesi corrispondenti ai bit a 1 quindi:

64 + 32 + 8 + 1 = 105
ps.
aresius lavori nell'IT di una famosa azienda che fa mobili?
__________________
.: NoS - Nitrous Oxide System :.
[En][gma] is offline   Reply With Quote
Old 3rd December 2010, 12:34   #3
Kaehell
l33t school
 
Kaehell's Avatar
 
Join Date: Mar 2008
Location: Zìria
Posts: 14,633
La tua soluzione da 1 1 e 2 ma ci sei quasi, la printf è giusta.. per i pesi sono dal cell e spiegare matematica impazzisco
__________________
"...the three great virtues of a programmer: laziness, impatience, and hubris." - Larry Wall
The e.Ngineering Xperience
BattleNet - Kaeh#2263 || Diablo3 - Kaeh
Kaehell is offline   Reply With Quote
Old 3rd December 2010, 12:44   #4
ramarnik
Registered User
 
Join Date: Jul 2009
Posts: 99
Somaro incoming!!!
Richiesta chiarimento,
"%d".. realmente cosa significa?? e si usa per la sola stampa a video dei numeri interi?

Un link a qualche glossario di questi %d o simili esiste o si va a memoria?

Nel codice postato sopra

Quote:
#include <stdio.h>
#include <stdlib.h>
void main()
{
unsigned int a;
unsigned int b;
unsigned int antani;
a=1;
b=a;
antani=a+b;
printf ("%d - %d - %d \n", a, b, antani);
system("pause");
}
In fondo mette il "system("pause");", ma se il programmino fosse finito lì, avrei dovuto mettere "return" per chiudere per terminare il tutto oppure è indifferente?

Inoltre nel mitico "return 0" lo 0 indica che non ritorna nessun valore ma per nessun valore cosa si intende? qui di valori ci sono.

(okey... avrò farcito di minchiate tutte le domane )

ps.: abbastanza chiaro il discorso delle variabili con definizio e assegnazione

Edit:
Le due librerie iniziali, la prima dice che ci sono dei valori di I/O e la seconda??

Ps. anche qui link a glossari da bookmarkare e spulciare in modo da ridurre le niubbodomande se possibile

Riedit: la risposta all'esercizio 1 è 1

Last edited by ramarnik; 3rd December 2010 at 12:49.
ramarnik is offline   Reply With Quote
Old 3rd December 2010, 13:05   #5
Gioz
viso alla parete
 
Gioz's Avatar
 
Join Date: Jan 2009
Location: Autogrill
Posts: 5,279
Quote:
Originally Posted by ramarnik View Post
In fondo mette il "system("pause");", ma se il programmino fosse finito lì, avrei dovuto mettere "return" per chiudere per terminare il tutto oppure è indifferente?

Inoltre nel mitico "return 0" lo 0 indica che non ritorna nessun valore ma per nessun valore cosa si intende? qui di valori ci sono.
system("pause") è indifferente dal return.
il return nell'esempio sopra non c'è perchè main() è stata dichiarata tornare un tipo void: è importante fare attenzione al tipo di ritorno.
void main() non torna nulla, quindi non c'è bisogno di return;
int main() torna un numero intero, quindi va messo il "return 0".

Negli altri casi:
int main() senza return: il compilatore genera un errore, perchè abbiamo dichiarato che main() torna un tipo intero quindi CI DEVE ESSERE.
void main() può non avere return, come abbiamo visto, oppure avere il solo return senza alcun valore:
Code:
void main() {
  printf("Hello, world");
  return;
}
Esercizio per chi è arrivato fin qui: in quali casi può servire il return senza valore? spiegate con un esempio.
__________________
(12:08) Gioz: ieri primo ban su agorà, un coppino di 24h
(12:09) Mr_MiMe: perchè? hai detto che dio esiste?

Gioz is offline   Reply With Quote
Old 3rd December 2010, 13:19   #6
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,290
sì Enigma, la printf con valori multipli funziona come hai scritto, ma volevo proprio le tre printf diverse per lasciare l'esempio semplice.

riguardo float e double, il discorso è molto complesso su come sono rappresentati in memoria. voler lasciare le cose semplici ha finito col renderle meno comprensibili.

Ffacciamo così: per ora non pensate a cosa significano i bit e considerate i float dei numeri reali (insomma, con la virgola) e i double dei numeri reali "più precisi". tanto basta in questa fase. adesso edito il primo post e cerco di correggere il tiro.



Ddiscorso a parte per i numeri interi. allora, facciamo un esempio con due bit, generalizzare a N bit sarà un attimo.

se abbiamo due bit, quante combinazioni escono? quando il primo bit è zero, l'altro può assumere due valori (0 e 1) e quando il primo bit va a uno, l'altro può ancora assumere due valori:

bit2 bit1
0 0
0 1
1 0
1 1

le combinazioni sono dunque 2X2 = 4. Nel caso di N bit, le combinazioni sono 2^N.

Come ricaviamo il valore decimale? Facciamo un esempio: prendiamo il numero binario 10.

pesi = 2 1
valori = 1 0

dobbiamo prendere i valori a "1" (in questo caso, solo il bit2) e sommare i loro pesi.

I pesi sono pari a 2 elevato al numero di posizione (partendo zero), quindi 2^0 = 1, 2^1 = 2. Se preferite termini matematici, dobbiamo fare una combinazione lineare dei pesi usando i coefficienti dati dai valori. In soldoni, questo:

valore decimale = 2*1 + 1*0 = 2 + 0 = 2


Esempio a quattro bit, numero 1001

pesi = 8 4 2 1
valori=1 0 0 1

valore decimale = 8*1 + 4*0 + 2*0 + 1*1 = 9


Spero risulti chiaro ora. Ad ogni modo, non è fondamentale la matematica binaria per conoscere il C, anche se aiuta.
__________________
Lode a Bacco, in saecula saeculorum.
Emergent
Arësius is offline   Reply With Quote
Old 3rd December 2010, 13:32   #7
ramarnik
Registered User
 
Join Date: Jul 2009
Posts: 99
Quote:
Originally Posted by Gioz View Post
system("pause") è indifferente dal return.
il return nell'esempio sopra non c'è perchè main() è stata dichiarata tornare un tipo void: è importante fare attenzione al tipo di ritorno.
void main() non torna nulla, quindi non c'è bisogno di return;
int main() torna un numero intero, quindi va messo il "return 0".

Negli altri casi:
int main() senza return: il compilatore genera un errore, perchè abbiamo dichiarato che main() torna un tipo intero quindi CI DEVE ESSERE.
void main() può non avere return, come abbiamo visto, oppure avere il solo return senza alcun valore:
Code:
void main() {
  printf("Hello, world");
  return;
}
Esercizio per chi è arrivato fin qui: in quali casi può servire il return senza valore? spiegate con un esempio.
Ok, quindi il tutto parte da come definisco il "main".
Le domande seguenti sono:
"return 0", lo zero è di prassi o potevo scrivere anche 1,2,3 e se si in che casi.

Mi fate un esempio stupido per capire quando il main ritorna un valore o in che caso io ho bisogno di definirlo "xxxxx main()" dove xxxxx è int o qualunque altra cosa ( che spiegerete piu avanti)?

edit: vi sto mettendo a dura prova dite la verità

Last edited by ramarnik; 3rd December 2010 at 13:34.
ramarnik is offline   Reply With Quote
Old 3rd December 2010, 13:33   #8
Pier4R
Ex falso quodlibet
 
Pier4R's Avatar
 
Join Date: Jul 2004
Location: equgpbc.r2.Frisia
Posts: 18,664
iscritto!

per stlib.h dovrebbe essere la libreria standard di C.
__________________
Ngi the e.FlameeXperience .Fe ! ngi.agorà@twitter (sottoscrivi per essere incluso)
You must play online: warSow EnemyTerritory + etpro quake 4 + q4max & quake 3 + cpma & quakelive Teeworlds! hoi2series

Ringrazio i grammar nazi che mi fanno comprendere gli errori ; my.IL
; lettere porno
Pier4R is offline   Reply With Quote
Old 3rd December 2010, 13:48   #9
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,867
ah scusate non avevo capito di dover assegnare i valori 1, 2 e 3... xD
vabbeh basta cambiare due cose:
Code:
#include <stdio.h>
#include <stdlib.h>
void main()
{
     unsigned int a;
     unsigned int b;
     unsigned int antani;
     a=1;
     b=2;
     antani=3;
     printf ("%d - %d - %d \n", a, b, antani);
     system("pause");
}
per rispondere a ramarnik:
io ho usato il system("pause"); per il semplice fatto che una volta avviato il programma almeno ti godi l'esecuzione...in quanto il programma si ferma in attesa di un input.
altrimenti con il solo return si chiude all'istante.

per il discorso %d neanch'io so cosa vuol dire...ma supponendo che verrà spiegato tra poco non ho fatto domande..
__________________
.: NoS - Nitrous Oxide System :.

Last edited by [En][gma]; 3rd December 2010 at 13:57.
[En][gma] is offline   Reply With Quote
Old 3rd December 2010, 13:48   #10
Nemo
~~~~~
 
Nemo's Avatar
 
Join Date: Feb 1999
Location: /index.php
Posts: 19,532
Approfondimento sulla rappresentazione dei numeri interi negativi: Complemento a due.
Nemo is offline   Reply With Quote
Old 3rd December 2010, 13:51   #11
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,290
Quote:
Originally Posted by ramarnik View Post
Ok, quindi il tutto parte da come definisco il "main".
Le domande seguenti sono:
"return 0", lo zero è di prassi o potevo scrivere anche 1,2,3 e se si in che casi.

Mi fate un esempio stupido per capire quando il main ritorna un valore o in che caso io ho bisogno di definirlo "xxxxx main()" dove xxxxx è int o qualunque altra cosa ( che spiegerete piu avanti)?

edit: vi sto mettendo a dura prova dite la verità
fai domande ottime.

Proprio come mi aspettavo, l'aver introdotto il return ha scatenato una serie di domande che avrei tenuto per dopo. anche a costo di darvi un hello world con un paio di warning

partiamo dicendo questo: c'è qualcuno cui interessa il tuo valore di ritorno? in questo momento, proprio no. se ci fossero degli altri programmi che utilizzano il tuo valore di ritorno per i propri calcoli, sarebbe fondamentale scegliere con oculatezza il valore.

altrimenti, uno vale l'altro, PURCHE' sia dello stesso tipo di quello indicato in xxxxxx.

tendenzialmente, è norma mettere zero che significa "alla grande baby"


se vuoi sperimentare un ritorno diverso da zero, prova a mettere istruzioni inventate nel tuo codice: il compilatore ti dirà un codice di errore. ecco, quello è il return del compilatore
__________________
Lode a Bacco, in saecula saeculorum.
Emergent

Last edited by Arësius; 3rd December 2010 at 13:54.
Arësius is offline   Reply With Quote
Old 3rd December 2010, 13:56   #12
[En][gma]
Registered User
 
[En][gma]'s Avatar
 
Join Date: Dec 2001
Posts: 2,867
aresius anche nel secondo esempio dei numeri binari e blabla non ho capito nulla..

ma non tanto il discorso in se, quanto la sua applicazione; mi sembra che non abbia nessuna attinenza con il resto, per questo non capisco.
__________________
.: NoS - Nitrous Oxide System :.
[En][gma] is offline   Reply With Quote
Old 3rd December 2010, 13:57   #13
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,290
mm... in soldoni, sto cercando di spiegare quali numeri si possono rappresentare con 32 bit. quasi quasi riscrivo quel pezzetto, adesso rifletto su come farlo.
__________________
Lode a Bacco, in saecula saeculorum.
Emergent
Arësius is offline   Reply With Quote
Old 3rd December 2010, 13:59   #14
Gioz
viso alla parete
 
Gioz's Avatar
 
Join Date: Jan 2009
Location: Autogrill
Posts: 5,279
Quote:
Originally Posted by ramarnik View Post
Ok, quindi il tutto parte da come definisco il "main".
Le domande seguenti sono:
"return 0", lo zero è di prassi o potevo scrivere anche 1,2,3 e se si in che casi.

Mi fate un esempio stupido per capire quando il main ritorna un valore o in che caso io ho bisogno di definirlo "xxxxx main()" dove xxxxx è int o qualunque altra cosa ( che spiegerete piu avanti)?

edit: vi sto mettendo a dura prova dite la verità
Storicamente il C vuole come prassi che main() ritorni un valore intero:
int main()
questo valore rappresenta un codice che dice a chi ha eseguito il programma (la shell, o un altro programma) se il nostro ha funzionato bene oppure no; sempre storicamente, si usa 0 per indicare "tutto ok".
Gli altri valori li decidiamo noi: es, possiamo decidere che 1 significa 'file non trovato', 2 'errore sul db', ecc. (chiaramente è bene elencare questi valori nella documentazione allegata al programma che stiamo creando).

Il "void main()" è più recente e permette di evitare il "return 0" alla fine del programma, è solo una comodità accettata dai compilatori moderni diciamo.
Però non vedrai mai "float main()", questo no, perchè il main() è il punto d'incontro tra il compilatore ed il tuo programma: chiaramente una minima convenzione ci dev'essere per farli funzionare senza conoscersi.
__________________
(12:08) Gioz: ieri primo ban su agorà, un coppino di 24h
(12:09) Mr_MiMe: perchè? hai detto che dio esiste?


Last edited by Gioz; 3rd December 2010 at 14:02.
Gioz is offline   Reply With Quote
Old 3rd December 2010, 14:01   #15
Arësius
Soft computer
 
Arësius's Avatar
 
Join Date: Feb 2000
Posts: 67,290
okay, hai editato: perfetto Gioz.

non voglio confondere chi sta seguendo il corso ed eviterò l'aneddoto.
__________________
Lode a Bacco, in saecula saeculorum.
Emergent

Last edited by Arësius; 3rd December 2010 at 14:03.
Arësius is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 21:29.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright 1998-2014 by NGI SpA