Dan's Brain

C

university

Gerarchia Elaboratore

  1. Digital Logic
  2. Microarchitecture
  3. Instruction Set Architecture
  4. Operating System
  5. Assembly
  6. High Level Language

Processo da file sorgente a eseguibile: vedi Compilazione e Linking

  1. Pre-processing ~ .c
  2. Compilazione ~ .s da qui il linguaggio diventa architecture specific
  3. Assembler ~ .o
  4. Linking ~ .o

Librerie: .so shared object

Gnu Compiler Collection - gcc

  • Front-end per il processo di compilazione-assemblaggio-linking
    • -c ferma dopo l’assemblaggio
    • -S ferma dopo la compilazione
    • -E ferma dopo il pre-processore
      • stampa in standard output

Il C nasce come linguaggio per lo sviluppo del OS Unix Il C e' un linguaggio tipato, ogni valore deve essere di un determinato tipo

Un file sorgente C puo' essere composto da:

  • direttive al preprocessore
  • dichiarazione tipi
  • dichiarazioni variabili globali
  • definizioni di funzioni come metodi Java ma non appartengono ad alcuna classe
  • funzione main()

direttive al preprocessore Le < > indicano al preprocessore che il file va cercato in percorsi predefiniti

include

es #include <stdio.h>

headers .h

contengono le dichiarazioni delle funzioni fornite dalle librerie

define

definisce nomi simbolici per valori costanti Associa due valori testuali

  • il numero di caratteri del nome simbolico é limitato: era 8
  • il pre-processore legge i moduli C in un passo

macro

una funzione ha un overhead – le macro no

Associa ad una signature una espressione

ifndef

se la costante simbolica non specificata non é stata ancora definita allora procede fino al endif

  • per evitare inclusioni multiple

ifdef

else

endif

Variabili

caratterizzate da un quadrupla (nome, tipo, indirizzo, valore)

L’indirizzo identifica la locazione di memoria alla quale il valore della variabile e' memorizzato e' assegnato dal OS a runtime o a compilazione

#include <stdio.h>
int i = 10;
int *ptr = &i;
int main(){
    printf("Indirizzo di i: \t%p\n", ptr);
    printf("Indirizzo di prt: \t%p\n", &prt); //il tipo di questa espressione e':
                                              //puntatore di puntatore a int
}

variabili globali

definite in un modulo possono essere usate da altri moduli previa dichiarazione

  • é buona regola definire le variabili globali in un intestazione

:ID: a862cf55-89ce-4612-88e9-ee94fd4b7b50

  • definire una variabile globale static significa renderla visibile solo nel modulo di definizione

int error_code;

extern int error_code;

Sequenze di escape

\ sequenza

\n newline \t tabulazione

Specificatori Formato

% specificatore

%d variabile %p pointer

entry point

unico: int main()

tipi primitivi

Nella definizione originaria di D.Ritchie il linguaggio non stabilisce alcuna dimensione per i dati in base al loro tipo

  • per portabilita' non si deve produrre un codice C dipendente dalla dimensione dei dati

int i;
short j = ;
int *ptr = NULL; //tipo: puntatore a interi

Non esistendo tipo Boolean:

  • 0 == false
  • valore diverso da 0 == true

int

short

long

unsigned int

float

double

char

void

es funzione che non restituisce valore

*

tipo puntatore

SEGV

Segmentation Fault

  • Puntatore non inizializzato non e' definito correttamente e punta a un’area di memoria protetta

enum

tipo enumerativo Permette di specificare valori opzionali

  • enum nome { valore= indicedipartenza [, valore]* }

Assegna un indice ad ogni valore, si puó anche specificare l’indice di partenza Possibile definire un enumerazione per false, true

* a funzione

La sintassi é tipo ritorno (* nomefunzione)([tipo argomenti]) puntatore in memoria instruzioni: la prima istruzione della funzione in particolare

  • il punto é che si crea una variabile, quindi durante l’esecuzione potrá cambiare.
    • uno stesso codice che utilizza un puntatore a funzione chiamerá funzioni diverse in momenti ed esecuzioni diverse
    • punterá sempre a funzioni con un simile prototipo

Funzioni

printf(char *format,…)

NB per fine linea

  • Windows: \r\n
  • Unix: \n
  • Macintosh: \r

scanf(char *format,…)

passo riferimenti a variabili dove memorizzare cio' che e' letto dallo stream di input, secondo il formato specificato dal programmatore

  • se lo stream e' vuoto la scaf si mette in attesa, l’OS lo inserisce in uno stato di wait fino a che lo stream non sara' riempito

  • Restituisce il numero di conversioni avvenute con successo

Utilizzando la scanf con il formato %s si leggono dallo stdin parole, ignorando spazi bianchi.

  • NB va passato come secondo argomento l’indirizzo di una variabile puntatore a char che contenga un numero di caratteri sufficientemente grande.

getchar()

restituisce un int(4 byte) per trattare altri casi oltre ai caratteri(1 byte)

Strutture Dati

array []

  • un array in C é sempre un const, un puntatore al primo elemento

  • le stringhe in realtá sono codificate con un array di char

  • per modificare i valori sono usati i puntatori

  • es array di char di stringhe

    char *weekdays[] = {"Mon", "Tue", "Wen", "Tue", "Fri"}; // un puntatore ad un puntatore
    // al primo oggetto dell'array
    
  • NB sull’uso di sizeof() sizeof(a)/sizeof(int) per sapere quanti interi conta l’array a (sizeof restituisce dimensioni in byte) MA ció non funziona se l’array e' passato come argomento di una funzione, in quanto sizeof(a) restituirá la dimensione del puntatore

    • il problema si puó risolvere passando un altro argomento n numero di argomenti

Per matrici la memoria é allocata linermente, indirizzo: a+i*LRighe+j Perció il compilatore ha bisogno di sapere la dimensione della seconda grandezza dell’array a[r][c]

void f(int a[][4]);
// dimensioni diverse per ogni riga:
int r1[1] = {1};
int r2[2] = {2, 2};
int r3[3] = {3, 3, 3};
int *a[] = {r1, r2, r3};

struct

Raggruppa dati di natura diversa

  • etichetta
    • non obbligatoria
  • campi
    • a cui si accede con a.x

A differenza dagli array posso assegnare tra loro le strutture definite utilizzando la stessa etichetta Il nome della struttura é interpretato come il valore della struttura in memoria. Questo tranne che nel caso sia lvalue in caso di assegnamento Infatti gli struct sono passati per valore, sempre a differenza degli array che vengono passati per riferimento

  • ogni volta che una struct sono passate o restituite vengono fatte copie dei dati poste sullo stack che vengono poi perse alla fine delle funzioni
    • spesso allora si passano per riferimento con void funzione(struct point *a)
      • cambia la sintassi utilizzando a->x per indicare il campo da modificare
        • concide con il deferenziamento: (*a).x

sizeof()

  • accetta anche le struct
  • spesso non coincide con le dimensioni dei suoi campi
    • questo per i vincoli di allineamento

typedef

  • typedef tipobase tipodefinito

    Su questi tipi non viene attuato un controllo stretto da parte del compilatore

        typedef enum { FALSE, TRUE } boolean;
    

union

Zona di memoria condivisa di diverse variabili, di tipi diversi. La sintassi é simile a una struct.

  • appunto memorizza in unione

Ridirigere lo standard input

programma < fileInput.txt Per utilizzare un file come stream di dati per

  • scanf
  • getchar

Traps al Sistema Operativo

Il Sistema Operativo gestisce una tabella di tutti i file aperti

  • ogni record memorizza le informazioni di quella particolare istanza
    • modalitá
    • offset

Funzioni di piú alto livello che interfacciano sui descrittori dei file

  • open()

  • read()

    • viene passato:
      • un fd
      • un void * ad un buffer di dimensione necessaria (per poter contenere count byte)
      • una size_t count
  • write()

  • lseek()

  • close()

Funzioni che utilizzano gli stream

  • fopen()
    • restituisce un FILE *
    • prende come parametri directory e flag r,w
  • fread()
  • fgets()
  • fseek()
  • fclose()

Allocazione dinamica della memoria dati

  • malloc(size_t size)
    • non inizializza a 0
  • calloc(size_t nmemb, size_t size)
    • inizializza a 0
    • alloca pe n-membri di size dimensione
  • realloc()
  • free()

Queste funzioni lavorano su void * ad aree dello heap