Cours de programmation séquentielle

Types

Orestis Malaspinas

Les types

Qu’est-ce qu’un type

  • Un système décrivant ce qui peut être contruit dans un programme.
  • Permet au compilateur ET au programmeur de raisonner sur un programme.
    
      4 + 12; //  = 16 (entier)
    1 + "a"; // aucun sens erreur de compilation (ou pas)
    
  • Deux sous-catégories de systèmes de type:
    • Statiquement ou dynamiquement typé (types connus à la compilation ou pas).
    • Faiblement ou fortement typé (les types peuvent pas être convertis implicitement ou pas).

Les types en rust

  • Langage statiquement et fortement typé: tous les types sont connus à la compilation et la conversion entre les types doit être explicite.
  • Les types sont inférés quand cela est possible.
  • Il est parfois nécessaire d’annoter le type explicitement.

    
      fn main() {
          let x:i32 = 5; // entier 32 bits dont le type est annoté
    
          let y = 5; // entier 32 bits dont le type est inféré
    
          println!("Ces deux lignes sont équivalentes x={} et y={}", x, y); // affichage
      }
      
  • Il exits plusieurs types de base:
    • Les entiers.
    • Les nombres à virgule flottante.
    • Les booléens.
    • Les charactères.

Les types numériques

Les entiers (1/3)

  • Il existe 5 tailles d’entiers (8, 16, 32, 64, et 128 bits) qui viennent en signé ou non-signé.
  • Également en taille dépendant de l’architecture
    • isize entier signé 32 ou 64 bits.
    • usize entier non-signé 32 ou 64 bits.
Longueur Signé Non-signé
8 bits i8 u8
16 bits i16 u16
32 bits i32 u32
64 bits i64 u64
128 bit i128 u128
32 ou 64 bits isize usize

Les entiers (2/3)

  • Par défaut un entier est de type i32.
  • Les types isize et usize sont typiquement pour indéxer des collections.
  • On peut spécifier le type d’un entier:
    • 42u8 est un entier 8 bits non signé.
    • 42isize est un entier de 32 ou 64 bits signé.
  • Pour améliorer la lisibilité on peut également ajout des "_":
    • On peut écrire 1000000 comme 1_000_000
  • On ne peut pas convertir implicitement d’un type à un autre.

    
    fn main() {
      let x:i64 = 5i32; // entier 32 bits dans une variable 64 bits
    }
      
  • On peut convertir entre les entiers à l’aide de as.

    
    fn main() {
      let x:i64 = 5i32 as i64; // entier 32 bits dans une variable 64 bits
    
      println!("Conversion de 32 en 64 bits pour x={}.", x); // affichage
    }
      

Les entiers (3/3)

  • En mode debug, un dépassement d’entier produira une erreur à l’exécution.
    
    fn main() {
      let x = 12341324;
      let y = 12341234;
    
      println!("L'entier x vaut {}.", (x*y) as i32); // affichage   
    }
      
  • Attention: En mode release, cela ne sera pas le cas.
    
    fn main() {
      let x:i32 = 12345678; 
      let y:i32 = 12345678; 
    
      println!("L'entier x vaut {}.", x*y); // affichage   
    }
      

Les nombres à virgule flottante

  • Il existe deux tailles de nombres à virgule flottante (32 et 64 bits):
    • f32,
    • f64.
  • Par défaut un nombre à virgule flottante est un f64
  • On ne peut pas convertir implicitement d’un type à un autre.

    
    fn main() {
      let x:f64 = 3.14159265359f32; // flottant 32 bits en flottant 64 bits
    }
      
  • On peut convertir entre les types de base avec as.

    
    fn main() {
      let x = 3.14159265359f64 as f32; // flottant 64 bits en flottant 32 bits
    
      println!("Conversion de pi en 32 bits, x = {}.", x); // affichage
    
      let y = 3.14159265359f64 as isize; // flottant 64 bits en entier 
    
      println!("Conversion de pi en entier 64 bits, y = {}.", y); // affichage
    }
      

Les opérations arithmétiques

  • Toutes les opérations arithmétiques standard: +, -, *, /, %

fn main() {
    let addition = 3 + 8;
    println!("La valeur de l'addition est: {}", addition);

    let soustraction = 3.5 - 8.1;
    println!("La valeur de la soustraction est: {}", soustraction);

    let multiplication = -3.33 * 3.33;
    println!("La valeur de la multiplication est: {}", multiplication);

    let division = 7 / 2; // division entière
    println!("La valeur de la division est: {}", division);
}

Assignations

  • Opérations arithmétiques et assignations: +=, -=, *=, /=, %=.

fn main() {
    let mut addition = 3;
    addition += 5;
    println!("La valeur de l'addition est: {}", addition);

    let mut multiplication = 3.5;
    multiplication *= - 8.1;
    println!("La valeur de la multiplication est: {}", multiplication);
}

Les types booléens

Les booléens

  • Une variable booléenne est de type bool.
  • Elle peut prendre deux valeurs:
    • true
    • false
  • La façon typique d’utiliser les booléens sont les structures de contrôle: if, while, …
  • Peut se convertir en entier (l’inverse est faux).

fn main() {
    let x = true; // Booléen inféré vrai
    println!("La variable x est {}.", x); // affichage

    let x: bool = false; // Booléen faux
    println!("La variable x est {}.", x); // affichage

    let x = false as i32; // Booléen faux
    let y = true as i32; // Booléen faux
    println!("False est {}, et True est {}.", x, y); // affichage
}

Les opérations booléennes

  • Comparaisons logiques ==, !=, &&, ||, <, >, <=, >=

    
    fn main() {
      let x = 3;
      let y = 8;
      println!("{} est-il égal à {}? {}", x, y, x == 8);
      println!("{} est-il différent de {}? {}", x, y, x != 8);
    }
      
  • Comparaisons bit à bit:
    • Et: &
    • Ou: ^
  • Comparaisons bit à bit et assignations: &=, ^=.

Le type charactère

Les charactères

  • Une variable de type charactère est notée char.
  • Elle contient toute valeur unicode scalaire, soit environ 137000 charactères (pas seulement du ASCII!).
  • Un charactère est toujours mis entre ’ ’.
  • Composants du type String.

fn main() {
    let x = 'a'; // Le charactère a

    println!("La variable x est {}.", x); // affichage

    let chat = '😻';

    println!("La variable chat est {}.", chat); // affichage
}

Les types composés

  • On peut contruire des types plus complexes (composés) à partir de types de base que nous venons de voir:
    • La type Struct
    • Le type Tuple
    • Le type Enum
    • Le type Array
    • Le type Vec
    • Le type String