264 lines
3.0 KiB
Markdown
264 lines
3.0 KiB
Markdown
# Chapitre 2 — Environnements et portabilité
|
||
|
||
## 2.1 C hébergé vs C freestanding
|
||
|
||
Il existe deux modes d’exécution du C.
|
||
|
||
Un environnement hébergé fournit :
|
||
- un OS
|
||
- une libc complète
|
||
- un point d’entrée `main`
|
||
|
||
```c
|
||
#include <stdio.h>
|
||
|
||
int main(void)
|
||
{
|
||
printf("Hello\n");
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
Un environnement freestanding est minimal.
|
||
|
||
```c
|
||
void start(void)
|
||
{
|
||
// code bas niveau
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2.2 Plateformes
|
||
|
||
Linux, Windows, macOS ont des APIs différentes.
|
||
Un programme C peut s’exécuter sur plusieurs systèmes.
|
||
Mais tous les systèmes sont différents.
|
||
|
||
---
|
||
- Linux
|
||
- API POSIX
|
||
- forte portabilité
|
||
- outils standards
|
||
---
|
||
- macOS
|
||
- basé sur UNIX
|
||
- proche de POSIX
|
||
- spécificités Apple
|
||
---
|
||
- Windows
|
||
- API spécifique (WinAPI)
|
||
- comportement différent sur certains points
|
||
- pas POSIX natif
|
||
---
|
||
- Android
|
||
- basé sur Linux
|
||
- libc spécifique (Bionic)
|
||
- contraintes mobiles
|
||
---
|
||
- Embarqué
|
||
- pas d’OS ou OS minimal
|
||
- ressources limitées
|
||
- accès direct au matériel
|
||
|
||
---
|
||
|
||
## 2.3 Architecture vs système
|
||
|
||
Un programme dépend de plusieurs couches.
|
||
|
||
Il faut distinguer :
|
||
|
||
- architecture (CPU)
|
||
- système (OS)
|
||
- compilateur
|
||
|
||
---
|
||
|
||
🔹 Architecture
|
||
|
||
Exemples :
|
||
|
||
- x86
|
||
- x86_64
|
||
- ARM
|
||
- RISC-V
|
||
|
||
Chaque architecture :
|
||
|
||
- a ses registres
|
||
- son alignement
|
||
- son endianness
|
||
|
||
---
|
||
|
||
🔹 Système
|
||
|
||
Le système fournit :
|
||
|
||
- fichiers
|
||
- processus
|
||
- mémoire
|
||
|
||
---
|
||
|
||
🔹 Compilateur
|
||
|
||
Il traduit le code C en binaire.
|
||
|
||
Exemples :
|
||
|
||
- gcc
|
||
- clang
|
||
- compilateurs embarqués
|
||
|
||
---
|
||
|
||
## 2.4 Endianness
|
||
|
||
L’endianness définit l’ordre des octets en mémoire.
|
||
|
||
🔹 Little endian
|
||
|
||
Octet faible en premier.
|
||
|
||
🔹 Big endian
|
||
|
||
Octet fort en premier.
|
||
|
||
---
|
||
|
||
Exemple :
|
||
|
||
```c
|
||
#include <stdio.h>
|
||
|
||
int main(void)
|
||
{
|
||
int x = 0x12345678;
|
||
unsigned char *p = (unsigned char*)&x;
|
||
|
||
printf("%02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]);
|
||
}
|
||
```
|
||
|
||
Le résultat dépend de l’architecture.
|
||
|
||
---
|
||
|
||
## 2.5 Taille des types
|
||
|
||
La taille des types n’est pas fixe.
|
||
|
||
---
|
||
|
||
Exemple :
|
||
|
||
```c
|
||
#include <stdio.h>
|
||
|
||
int main(void)
|
||
{
|
||
printf("%zu\n", sizeof(int));
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2.6 Ce qui est portable
|
||
|
||
Code portable :
|
||
|
||
- respecte la norme
|
||
- évite les extensions
|
||
- évite les hypothèses
|
||
|
||
---
|
||
|
||
Exemple — non portable
|
||
|
||
```c
|
||
int main(void)
|
||
{
|
||
int x = 2147483647 + 1; // overflow
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
Le comportement n’est pas défini.
|
||
|
||
---
|
||
|
||
Exemple — portable
|
||
|
||
```c
|
||
#include <stdint.h>
|
||
|
||
int main(void)
|
||
{
|
||
int32_t x = 2147483647;
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2.7 Dépendances système
|
||
|
||
Certains appels dépendent du système.
|
||
|
||
---
|
||
|
||
Exemple :
|
||
|
||
```c
|
||
#include <stdlib.h>
|
||
|
||
int main(void)
|
||
{
|
||
system("ls"); // Linux uniquement
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2.8 Abstraction
|
||
|
||
|
||
Pour être portable, il faut abstraire.
|
||
|
||
Cela signifie :
|
||
|
||
- isoler le code dépendant
|
||
- utiliser des interfaces
|
||
|
||
--
|
||
|
||
Exemple :
|
||
|
||
```c
|
||
void afficher_message(void)
|
||
{
|
||
#ifdef _WIN32
|
||
// Code Windows
|
||
#else
|
||
// Code Linux ?
|
||
#endif
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 2.9 Bonnes pratiques
|
||
|
||
- utiliser <stdint.h>
|
||
- éviter les tailles implicites
|
||
- éviter UB
|
||
- tester sur plusieurs plateformes
|
||
- isoler le code système
|