Skip to content
Snippets Groups Projects
base_1.md 14.7 KiB
Newer Older
orestis.malaspin's avatar
orestis.malaspin committed
---
title: "Base I"
orestis.malaspin's avatar
orestis.malaspin committed
date: "2020-09-16"
orestis.malaspin's avatar
orestis.malaspin committed
---

# Historique (1/2)

- Conçu initialement pour la programmation des systèmes d’exploitation (UNIX).
- Créé par Dennis Ritchie à Bell Labs en 1972 dans la continuation de CPL, BCPL et B.
- Standardisé entre 1983 et 1988 (ANSI C).
- La syntaxe de C est devenue la base d’autres langages comme C++, Objective-C, Java, Go, C#, Rust, etc.
- Révisions plus récentes, notamment C99, C11, puis C18.

# Historique (2/2)

- Développement de C lié au développement d’UNIX.
- UNIX a été initialement développé en assembleur:
orestis.malaspin's avatar
orestis.malaspin committed
    - instructions de très bas niveau
    - instructions spécifiques à l’architecture du processeur.
- Pour rendre UNIX portable, un langage de *haut niveau* (en 1972) était nécessaire.
- Comparé à l’assembleur, le C est :
    - Un langage de "haut niveau": C offre des fonctions, des structures de données, des constructions de contrôle de flots (`while`{.C}, `for`{.C}, etc).
    - Portable: un programme C peut être exécuté sur un *très grand nombre* de plateformes (il suffit de recompiler le *même code* pour l’architecture voulue).

# Qu'est-ce que le C?

orestis.malaspin's avatar
orestis.malaspin committed
- "Petit langage simple" (en 2020).
- Langage compilé, statiquement (et faiblement) typé, procédural, portable, très efficace.
orestis.malaspin's avatar
orestis.malaspin committed
- Langage "bas niveau" (en 2020): management explicite et manuelle de la mémoire (allocation/désallocation), grande liberté pour sa manipulation.
- Pas de structures de haut niveau: chaînes de caractères, vecteurs dynamiques, listes, ...
- Aucune validation ou presque sur la mémoire (pointeurs, overflows, ...).

# Exemple de programme

```C
#include <stdio.h>
#include <stdlib.h>
int main() {
  printf("Enter n: "); // affichage
  int n = 0; // déclaration et initialisation de n
  scanf("%d", &n); // entrée au clavier
  int sum = 0; // déclaration et initialisation de sum
  for (int i = 0; i <= n; ++i) { // boucle
    sum += i;
  }
  printf("Sum of the %d first integers: %d\n", n, sum);
  if (sum != n * (n+1) / 2) { // branchement cond.
    printf("Error: the answer is wrong.\n");
    return EXIT_FAILURE; // code d'erreur
  }
  return EXIT_SUCCESS; // code de réussite
}
```

# Génération d'un exécutable

- Pour pouvoir être exécuté un code C doit être d'abord compilé (avec `gcc` ou `clang`).
- Pour un code `prog.c` la compilation "minimale" est

    ```bash
    $ clang prog.c
    $ ./a.out # exécutable par défaut
    ```

- Il existe une multitude d'options de compilation:

orestis.malaspin's avatar
orestis.malaspin committed
    $ clang -O1 -std=c11 -Wall -Wextra -g porg.c -o prog 
    -fsanitize=address -fsanitize=leak -fsanitize=undefined
    ```
    1. `-std=c11` utilisation de C11.
    2. `-Wall et -Wextra` activation des warnings.
orestis.malaspin's avatar
orestis.malaspin committed
    3. `-fsanitize=…`  contrôles d’erreurs à l’exécution (coût en performance).
    4. `-g` symboles de débogages sont gardés.
    5. `-o` défini le fichier exécutable à produire en sortie.
    6. `-O1`, `-O2`, `-O3`: activation de divers degrés d'optimisation



# La simplicité de C?

orestis.malaspin's avatar
orestis.malaspin committed
## 32 mots-clé et c'est tout

---------------- -------------- ---------------- ---------------
`auto`{.C}       `double`{.C}   `int`{.C}        `struct`{.C}   
`break`{.C}      `else`{.C}     `long`{.C}       `switch`{.C}   
`case`{.C}       `enum`{.C}     `register`{.C}   `typedef`{.C}  
`char`{.C}       `extern`{.C}   `return`{.C}     `union`{.C}    
`const`{.C}      `float`{.C}    `short`{.C}      `unsigned`{.C} 
`continue`{.C}   `for`{.C}      `signed`{.C}     `void`{.C}
`default`{.C}    `goto`{.C}     `sizeof`{.C}     `volatile`{.C}
`do`{.C}         `if`{.C}       `static`{.C}     `while`{.C}
---------------- -------------- ---------------- ---------------

# Déclaration et typage

En C lorsqu'on veut utiliser une variable (ou une constante), on doit déclarer son type

```C
const double two = 2.0; // déclaration et init.
int x;   // déclaration (instruction)
char c;  // déclaration (instruction)
x = 1;   // affectation (expression)
c = 'a'; // affectation (expression)
int y = x; // déclaration et initialisation en même temps
int a, b, c; // déclarations multiples
a = b = c = 1; // init. multiples
orestis.malaspin's avatar
orestis.malaspin committed
# Types de base (1/4)

## Numériques

Type                               Signification (**gcc pour x86-64**)            
---------------------------------- ---------------------------------------------
`char`{.C}, `unsigned char`{.C}    Entier signé/non-signé 8-bit
`short`{.C}, `unsigned short`{.C}  Entier signé/non-signé 16-bit
`int`{.C}, `unsigned int`{.C}      Entier signé/non-signé 32-bit
`long`{.C}, `unsigned long`{.C}    Entier signé/non-signé 64-bit
`float`{.C}                        Nombre à virgule flottante, simple précision
`double`{.C}                       Nombre à virgule flottante, double précision
---------------------------------- ---------------------------------------------

**La signification de `short`{.C}, `int`{.C}, ... dépend du compilateur et de l'architecture.**

orestis.malaspin's avatar
orestis.malaspin committed
# Types de base (2/4)

Voir `<stdint.h>` pour des représentations **portables**

Type                               Signification
---------------------------------- ---------------------------------------------
`int8_t`{.C}, `uint8_t`{.C}        Entier signé/non-signé 8-bit
`int16_t`{.C}, `uint16_t`{.C}      Entier signé/non-signé 16-bit
`int32_t`{.C}, `uint32_t`{.C}      Entier signé/non-signé 32-bit
`int64_t`{.C}, `uint64_t`{.C}      Entier signé/non-signé 64-bit
---------------------------------- ---------------------------------------------

orestis.malaspin's avatar
orestis.malaspin committed
# Types de base (3/4)

## Booléens

- Le ANSI C n'offre pas de booléens.
- L'entier `0`{.C} signifie *faux*, tout le reste *vrai*.
- Depuis C99, la librairie `stdbool` met à disposition un type `bool`{.C}.
- En réalité c'est un entier:
  - $1 \Rightarrow$ `true`{.C}
  - $0 \Rightarrow$ `false`{.C}
orestis.malaspin's avatar
orestis.malaspin committed
- On peut les manipuler comme des entier (les sommer, les multiplier, ...).
orestis.malaspin's avatar
orestis.malaspin committed
# Quiz: booléens

## [Quiz: booléens](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1032492)

<!-- TODO Quiz en ligne -->
<!-- ```C
if (42) { /* vrai */ }

int x = 100;
if (x == 4) { /* faux */ }
if (x) { /* vrai */ }

orestis.malaspin's avatar
orestis.malaspin committed
int x = 100;
while (x−−) { /* répète tant que x est différent de 0 */ }

if (0) { /* faux */ }
if (i = 4) { /* vrai */ }
if (i = 0) { /* faux */ }

#include <stdbool.h>

bool x = true;
if (x) { /* vrai */ }
``` -->

orestis.malaspin's avatar
orestis.malaspin committed
# Types de base (4/4)

## Conversions

- Les conversions se font de manière:
  - Explicite:
    ```C
    int a = (int)2.8;
    double b = (double)a;
    int c = (int)(2.8+0.5);
    ```
  - Implicite:
    ```C
    int a = 2.8; // warning, si activés, avec clang
    double b = a + 0.5;
    char c = b; // pas de warning...
    int d = 'c';
    ```

orestis.malaspin's avatar
orestis.malaspin committed
# Quiz: conversions

## [Quiz: conversions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033446)

<!-- TODO Quiz en ligne -->
<!-- ```C
int a = (int)2.8; // 2

double b = 2.85;
int c = b + 0.5; // 3

int d = a + 0.5; // 2

bool d = 2.78; // 0
bool e = 1.0; // 1
``` -->

orestis.malaspin's avatar
orestis.malaspin committed
# Expressions et opérateurs (1/6)

Une expression est tout bout de code qui est **évalué**.

## Expressions simples

- Pas d'opérateurs impliqués.
- Les littéraux, les variables, et les constantes.

```C
const int L = -1; // 'L' est une constante, -1 un littéral
int x = 0;        // '0' est un litéral
int y = x;        // 'x' est une variable
int z = L;        // 'L' est une constante
```

## Expressions complexes

- Obtenues en combinant des *opérandes* avec des *opérateurs*

```C
int x;     // pas une expression (une instruction)
x = 4 + 5; // 4 + 5 est une expression
           // dont le résultat est affecté à 'x'
```

orestis.malaspin's avatar
orestis.malaspin committed
# Expressions et opérateurs (2/6)

## Opérateurs relationnels

Opérateurs testant la relation entre deux *expressions*:

  - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}.

| Opérateur | Syntaxe      | Résultat             |
|-----------|--------------|----------------------|
| `<`{.C}   | `a < b`{.C}  | 1 si a <  b; 0 sinon |
| `>`{.C}   | `a > b`{.C}  | 1 si a >  b; 0 sinon |
| `<=`{.C}  | `a <= b`{.C} | 1 si a <= b; 0 sinon |
| `>=`{.C}  | `a >= b`{.C} | 1 si a >= b; 0 sinon |
| `==`{.C}  | `a == b`{.C} | 1 si a == b; 0 sinon |
| `!=`{.C}  | `a != b`{.C} | 1 si a != b; 0 sinon |

orestis.malaspin's avatar
orestis.malaspin committed
# Expressions et opérateurs (3/6)

## Opérateurs logiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `&&`{.C}  | `a && b`{.C} | ET logique           |
| `||`{.C}  | `a || b`{.C} | OU logique           |
| `!`{.C}   | `!a`{.C}     | NON logique          |

orestis.malaspin's avatar
orestis.malaspin committed
# Quiz: opérateurs logiques

## [Quiz: opérateurs logiques](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033629)

<!-- TODO: Quiz -->
<!-- ```C
1 && 0 == 0
7 && 3 == 1
4 || 3 == 1
!34 == 0
!0 == 1

Soit n un unsigned char initialisé à 127:
!n == 0
``` -->

orestis.malaspin's avatar
orestis.malaspin committed
# Expressions et opérateurs (4/6)

## Opérateurs arithmétiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `+`{.C}   | `a + b`{.C}  | Addition             |
| `-`{.C}   | `a - b`{.C}  | Soustraction         |
| `*`{.C}   | `a * b`{.C}  | Multiplication       |
| `/`{.C}   | `a / b`{.C}  | Division             |
| `%`{.C}   | `a % b`{.C}  | Modulo               |

orestis.malaspin's avatar
orestis.malaspin committed
# Expressions et opérateurs (5/6)

## Opérateurs d'assignation

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
orestis.malaspin's avatar
orestis.malaspin committed
| `=`{.C}   | `a = b`{.C}  | Affecte la valeur `b` à la variable `a`     |
|           |              | et retourne la valeur de `b`                |
| `+=`{.C}  | `a += b`{.C} | Additionne la valeur de `b` à `a` et        |
|           |              | assigne le résultat à `a`.                  |
| `-=`{.C}  | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `*=`{.C}  | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `/=`{.C}  | `a /= b`{.C} | Divise la valeur de `b` à `a` et            |
|           |              | assigne le résultat à `a`.                  |
| `%=`{.C}  | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et |
|           |              | assigne le résultat à `a`.                  |
orestis.malaspin's avatar
orestis.malaspin committed

orestis.malaspin's avatar
orestis.malaspin committed
# Expressions et opérateurs (6/6)
orestis.malaspin's avatar
orestis.malaspin committed

## Opérateurs d'assignation (suite)

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
orestis.malaspin's avatar
orestis.malaspin committed
| `++`{.C}  | `++a`{.C}    | Incrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a += 1`).            |
orestis.malaspin's avatar
orestis.malaspin committed
| `--`{.C}  | `--a`{.C}    | Décrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a -= 1`).            |
orestis.malaspin's avatar
orestis.malaspin committed
| `++`{.C}  | `a++`{.C}    | Retourne `a`{.C} et incrémente `a` de 1.    |
| `--`{.C}  | `a--`{.C}    | Retourne `a`{.C} et décrémente `a` de 1.    |
orestis.malaspin's avatar
orestis.malaspin committed
# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (1/2)

## Syntaxe

```C
if (expression) {
    instructions;
} else if (expression) { // optionnel
                         // il peut y en avoir plusieurs
    instructions;
} else {
    instructions; // optionnel
}
```

```C
if (x) { // si x s'évalue à `vrai`
    printf("x s'évalue à vrai.\n");
} else if (y == 8) { // si y vaut 8
    printf("y vaut 8.\n");
    printf("Ni l'un ni l'autre.\n");
orestis.malaspin's avatar
orestis.malaspin committed
# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (2/2)
int x, y;
x = y = 3;
    printf("x = 2 est vrai.\n");
else if (y < 8)
    printf("y < 8.\n");
else if (y == 3)
    printf("y vaut 3 mais cela ne sera jamais affiché.\n");
    printf("Ni l'un ni l'autre.\n");
    x = -1; // toujours évalué
```

orestis.malaspin's avatar
orestis.malaspin committed
# Quiz: `if ... else`{.C}
orestis.malaspin's avatar
orestis.malaspin committed
## [Quiz: `if ... else`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033916)
orestis.malaspin's avatar
orestis.malaspin committed
# Les variables (1/2)

## Variables et portée

- Une variable est un identifiant, qui peut être liée à une valeur (un expression).
- Une variable a une **portée** qui définit où elle est *visible* (où elle peut être accédée).
- La portée est **globale** ou **locale**.
- Une variable est **globale** est accessible à tout endroit d'un programme et doit être déclarée en dehors de toute fonction.
- Une variable est **locale** lorsqu'elle est déclarée dans un **bloc**, `{...}`{.C}.
- Une variable est dans la portée **après** avoir été déclarée.

orestis.malaspin's avatar
orestis.malaspin committed
# Les variables (2/2)

## Exemple 

```C
int bar() { // x, y pas visibles ici, max oui }

int foo() {
    int x = 1; // x est locale à foo
    {
        // x est visible ici, y pas encore
        int y = 2;
        bar(); // ni x ni y sont visible dans bar()
    } // y est détruite à la sortie du bloc
} // x est à la sortie de foo

float max; // variable globale accessible partout

int main() {
    int z; // locale, à main
} // z est détruite ici, max aussi
```

<!-- TODO: quiz, compile, compile pas -->
<!-- ```C
int main() {
    global = 1;
} // COMPILE PAS
```

```C
int main() {
    int global = 1;
    {
        printf("global = %d", global);
    }
} // COMPILE
```

```C
int local;

int main() {
    local = 1;
    {
        printf("local = %d", local);
    }
} // COMPILE
```

```C
#include <stdio.h>
int local = 0;

int main() {
    int local = -1;
    {
        int local = 1;
        printf("local = %d\n", local);
    }
} // COMPILE
``` -->

orestis.malaspin's avatar
orestis.malaspin committed
# Quiz: compile ou compile pas?

## [Quiz: compile ou compile pas](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033948)

orestis.malaspin's avatar
orestis.malaspin committed
# Entrées/sorties: `printf()`{.C} (1/2)
orestis.malaspin's avatar
orestis.malaspin committed

## Généralités

- La fonction `printf()`{.C} permet d'afficher du texte sur le terminal:

    ```C
    int printf(const char *format, ...);
    ```
- Nombre d'arguments variables.
- `format`{.C} est le texte, ainsi que le format (type) des variables à afficher.
- Les arguments suivants sont les expressions à afficher.

orestis.malaspin's avatar
orestis.malaspin committed
# Entrées/sorties: `printf()`{.C} (2/2)
orestis.malaspin's avatar
orestis.malaspin committed

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Hello world.\n");
    int val = 1;
    printf("Hello world %d time.\n", val);
    printf("%f squared is equal to %f.\n", 2.5, 2.5*2.5);
    return EXIT_SUCCESS;
}
```

orestis.malaspin's avatar
orestis.malaspin committed
# Entrées/sorties: `scanf()`{.C} (1/2)
orestis.malaspin's avatar
orestis.malaspin committed

## Généralités

- La fonction `scanf()`{.C} permet de lire du texte formaté entré au clavier:

    ```C
    int scanf(const char *format, ...);
    ```

- `format`{.C} est le format des variables à lire (comme `printf()`{.C}).
- Les arguments suivants sont les variables où sont stockées les valeurs lues.

orestis.malaspin's avatar
orestis.malaspin committed
# Entrées/sorties: `scanf()`{.C} (2/2)
orestis.malaspin's avatar
orestis.malaspin committed

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Enter 3 numbers: \n");
    int i, j, k;
    scanf("%d %d %d", &i, &j, &k);
    printf("You entered: %d %d %d\n", i, j, k);
    
    return EXIT_SUCCESS;
}