Salta al contenuto
Note per Studenti Funzioni in C

Funzioni in C

In questa pagina 7

Definizione e prototipo

c
#include <stdio.h>

double media(int a, int b);          /* prototipo (dichiarazione) */

int main(void) {
    printf("%.1f\n", media(3, 4));   /* 3.5 */
    return 0;
}

double media(int a, int b) {         /* definizione */
    return (a + b) / 2.0;
}

Passaggio per valore

In C gli argomenti sono sempre copiati nei parametri: modificare un parametro non modifica la variabile del chiamante.

c
void incrementa(int n) {
    n++;                 /* modifica la copia locale */
}

int main(void) {
    int x = 5;
    incrementa(x);
    printf("%d\n", x);   /* 5 */
}

Per modificare una variabile del chiamante si passa il suo indirizzo:

c
void incrementa(int *p) {
    (*p)++;              /* modifica la variabile puntata */
}
/* chiamata: incrementa(&x); */

void scambia(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

Gli array sono un caso particolare: passando un array si passa l'indirizzo del primo elemento, quindi la funzione può modificarlo e non ne conosce la lunghezza, che va passata a parte (vedi Array e stringhe in CArray di dimensione fissa in memoria contigua, inizializzazione, nessun controllo sugli indici, passaggio a funzioni con la lunghezza, matrici; stringhe come array di char terminati da '\0' e funzioni di string.h.Array e stringhe in C →).

Confronto con Python, dove si passano riferimenti a oggetti: Funzioni in Pythondef e return, parametri posizionali, con nome e con valore predefinito, *args e **kwargs; passaggio per riferimento a oggetto; ambito delle variabili LEGB; docstring, type hint, lambda.Funzioni in Python →.

Ambito e durata delle variabili

Tipo di variabile Dove si dichiara Visibilità Durata
locale (automatica) dentro un blocco { } dal punto di dichiarazione alla fine del blocco dall'ingresso all'uscita del blocco (sullo stack)
parametro intestazione corpo della funzione come le locali
globale fuori da ogni funzione tutto il file (dal punto di dichiarazione) intero programma
locale static dentro una funzione con static la funzione intero programma: conserva il valore tra le chiamate
c
int conta_chiamate(void) {
    static int n = 0;    /* inizializzata una sola volta */
    return ++n;
}

Non restituire mai l'indirizzo di una variabile locale: alla fine della funzione quella memoria non esiste più (vedi Gestione della memoria in CSegmenti di memoria di un processo (codice, dati statici, stack, heap); durata delle variabili; allocazione dinamica con malloc, calloc, realloc e free; errori classici: memory leak, dangling pointer, double free, buffer overflow; strumenti di controllo.Gestione della memoria in C →).

Compilazione separata e header

Programmi più grandi si dividono in più file. Il file header .h contiene i prototipi (l'interfaccia); il .c le definizioni.

geometria.hc
#ifndef GEOMETRIA_H
#define GEOMETRIA_H

double area_cerchio(double r);

#endif
geometria.cc
#include "geometria.h"

double area_cerchio(double r) {
    return 3.141592653589793 * r * r;
}
main.cc
#include <stdio.h>
#include "geometria.h"

int main(void) {
    printf("%f\n", area_cerchio(2.0));
    return 0;
}
> gcc -Wall -o prog main.c geometria.c

Librerie standard utili

<stdio.h> I/O, <stdlib.h> (malloc, free, abs, rand, exit), <math.h> (sqrt, pow, fabs; su Linux compilare con -lm), <string.h> stringhe, <ctype.h> (isdigit, toupper), <stdbool.h>, <limits.h>.

Ricorsione

Identica a Python (RicorsioneFunzioni che chiamano se stesse: caso base e passo ricorsivo, stack delle chiamate, esempi su numeri, stringhe e liste, ricorsione multipla e suo costo, divide et impera, confronto con l'iterazione.Ricorsione →): ogni chiamata ha il suo record di attivazione sullo stack.

c
long long fattoriale(int n) {
    return n <= 1 ? 1 : n * fattoriale(n - 1);
}

Errori tipici

  • Chiamare una funzione prima di dichiararla.
  • Aspettarsi che una funzione modifichi un int passato per valore.
  • Funzione non void che in qualche ramo non esegue return: il valore restituito è indefinito.
  • Prototipo e definizione con tipi diversi.

Teoria collegata