This commit is contained in:
2026-04-09 16:11:56 +02:00
parent 777b0573c0
commit 4227d52f23

262
ch002-env.md Normal file
View File

@@ -0,0 +1,262 @@
# Chapitre 2 — Environnements et portabilité
## 2.1 C hébergé vs C freestanding
Il existe deux modes dexécution du C.
Un environnement hébergé fournit :
- un OS
- une libc complète
- un point dentré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 sexé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 dOS 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
Lendianness définit lordre 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 larchitecture.
---
## 2.5 Taille des types
La taille des types nest 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 nest 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