Aller au contenu

Histoire de C et C++

C est ne en 1972 dans les laboratoires Bell, conçu par Dennis Ritchie et Ken Thompson comme langage de système pour reecrire Unix. C++ est apparu en 1979 sous la plume de Bjarne Stroustrup comme extension orientée objet de C, sans rompre la compatibilité avec lui. Ces deux langages, gouvernes aujourd'hui par des comites ISO distincts (WG14 pour C, WG21 pour C++), continuent d'évoluer activement avec des standards publies régulièrement.


Origines de C — Bell Labs et Unix

En 1969, Ken Thompson commence à écrire Unix en assembleur PDP-7. Il crée d'abord le langage B (dérivé de BCPL) pour faciliter le portage. Dennis Ritchie reprend B et le transforme en C entre 1969 et 1973, ajoutant notamment un système de types et l'arithmetique sur les pointeurs.

La version de C qui accompagne Unix V4 (1973) est suffisamment mature pour reecrire le noyau Unix en C, un acte fondateur : pour la première fois, un système d'exploitation de production est écrit dans un langage de haut niveau portable.

/* Premier exemple typique de l'ere K&R — style C classique */
/* Compilation : cc hello.c -o hello                        */
#include <stdio.h>

main()
{
    printf("hello, world\n");
}

K&R C

Le livre "The C Programming Language" de Brian Kernighan et Dennis Ritchie (1978, dit "K&R") a standardise de facto le langage avant la norme ANSI. La première edition ne déclaré pas le type de retour de main, convention abandonnee avec C89.


Chronologie des standards C

Le langage C a été standardise par l'ANSI en 1989, puis repris par l'ISO. Chaque révision apporte des fonctionnalités tout en preservant la compatibilité avec les programmes existants.

Standard Année Évolutions majeures
K&R C 1978 Livre de référence, pas de standard formel
C89/C90 1989 Première norme ANSI/ISO, prototypes de fonctions, void, const, enum
C99 1999 Types int64_t, tableaux a longueur variable, // commentaires, inline
C11 2011 Threads natifs (<threads.h>), _Generic, _Atomic, assertions statiques
C17/C18 2018 Correction de défauts C11, pas de nouvelles fonctionnalités majeures
C23 2023 typeof, nullptr, [[nodiscard]], constexpr en C, #embed, bool natif
/* Demonstration de fonctionnalites C99 et C11 */
/* Compilation : gcc -std=c11 -Wall demo.c -o demo */
#include <stdio.h>
#include <stdint.h>   /* int64_t, uint32_t — depuis C99 */
#include <stdbool.h>  /* bool, true, false — depuis C99  */
#include <stdatomic.h>/* atomic_int — depuis C11          */

/* Genericite de type avec _Generic (C11) */
#define afficher(x) _Generic((x),   \
    int:     printf("int: %d\n",    (x)), \
    double:  printf("double: %f\n", (x)), \
    default: printf("autre\n")           \
)

int main(void) {
    int64_t grand = INT64_MAX;
    bool actif = true;
    atomic_int compteur = 0;

    /* Tableau a longueur variable (VLA) — C99 */
    int n = 5;
    int tableau[n];
    for (int i = 0; i < n; i++) {  /* Declaration dans for — C99 */
        tableau[i] = i * i;
    }

    afficher(42);      /* affiche : int: 42    */
    afficher(3.14);    /* affiche : double: 3.140000 */

    printf("grand = %" PRId64 ", actif = %d\n", grand, actif);
    return 0;
}

Origines de C++ — "C with Classes"

En 1979, Bjarne Stroustrup, alors doctorant a Cambridge puis chercheur aux Bell Labs, commence à travailler sur "C with Classes". Il est frustre par les limitations de Simula (le premier langage a classes) pour écrire des systèmes performants, et par les limitations de C pour structurer de grands programmes.

Les objectifs initiaux de Stroustrup :

  • Ajouter l'abstraction de données et l'orienté objet sans sacrifier les performances de C
  • Garantir la compatibilité ascendante : tout programme C valide doit compiler en C++
  • "Zero-overhead abstraction" : une abstraction non utilisée ne doit pas couter de performance

Le nom "C++" est donne en 1983 (l'opérateur ++ signifiant "une version après C"). La première version commerciale est disponible en 1985 avec le compilateur Cfront.

// Exemple d'encapsulation C++ — classe Vector minimal
// Compilation : g++ -std=c++17 vector.cpp -o vector
#include <iostream>
#include <stdexcept>

class Vector {
public:
    // Constructeur avec allocation dynamique
    explicit Vector(int taille) : taille_(taille), data_(new double[taille]) {
        for (int i = 0; i < taille_; ++i) data_[i] = 0.0;
    }

    // Destructeur — libere la memoire automatiquement (RAII)
    ~Vector() { delete[] data_; }

    // Operateur d'acces avec verification des bornes
    double& operator[](int i) {
        if (i < 0 || i >= taille_) throw std::out_of_range("Index hors bornes");
        return data_[i];
    }

    int taille() const { return taille_; }

private:
    int taille_;
    double* data_;
};

int main() {
    Vector v(3);
    v[0] = 1.0; v[1] = 2.0; v[2] = 3.0;
    for (int i = 0; i < v.taille(); ++i)
        std::cout << v[i] << " ";  // 1 2 3
    std::cout << std::endl;
    return 0;
}

Chronologie des standards C++

Standard Année Évolutions majeures
C++98 1998 Première norme ISO, STL (vector, map, string), exceptions, templates
C++03 2003 Correction de défauts C++98, pas de nouvelles fonctionnalités
C++11 2011 Move semantics, auto, nullptr, lambdas, std::thread, unique_ptr, range-for
C++14 2014 auto dans les lambdas, make_unique, lambdas génériques, variable templates
C++17 2017 if constexpr, std::optional, std::variant, structured bindings, parallel algorithms
C++20 2020 Concepts, ranges, coroutines, modules, std::span, std::format, consteval
C++23 2023 std::expected, std::print, import std, deducing this, stacktrace, ranges ameliores
// Demonstration des evolutions C++11 a C++20
// Compilation : g++ -std=c++20 -Wall moderne.cpp -o moderne
#include <iostream>
#include <vector>
#include <optional>
#include <ranges>
#include <format>  // C++20

// Concept C++20 — contrainte sur le type T
template<typename T>
concept Numerique = std::integral<T> || std::floating_point<T>;

// Fonction contrainte par un concept
template<Numerique T>
T carre(T x) { return x * x; }

// std::optional — retourne un resultat ou rien (C++17)
std::optional<double> diviser(double a, double b) {
    if (b == 0.0) return std::nullopt;
    return a / b;
}

int main() {
    // auto + initializer_list + range-for (C++11)
    auto nombres = std::vector<int>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // Ranges + views (C++20) — pipeline declaratif
    auto pairs_carres = nombres
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * n; });

    for (int v : pairs_carres)
        std::cout << v << " ";  // 4 16 36 64 100
    std::cout << "\n";

    // std::format (C++20) — formatage type-safe
    std::cout << std::format("carre(7) = {}\n", carre(7));

    // std::optional (C++17)
    if (auto r = diviser(10.0, 3.0); r.has_value())
        std::cout << std::format("10/3 = {:.4f}\n", *r);

    return 0;
}

Comites ISO WG14 et WG21

C et C++ sont gouvernes par deux groupes de travail ISO distincts :

Comite Langage Cycle de release Dépôt public
WG14 C ~6 ans open-std.org/JTC1/SC22/WG14
WG21 C++ 3 ans open-std.org/JTC1/SC22/WG21

Le comite WG21 suit un cycle triennal strict depuis C++11. Les propositions (appelées "papers") sont soumises, discutees lors de réunions bi-annuelles, et acceptees ou rejetees. Les papiers sont numerotes PXXXXRN (P pour proposal, X numéro, R révision).

Suivre les évolutions de C++

Le site cppreference.com est la référence la plus à jour pour les standards C et C++. Pour suivre les papiers en cours, compiler.explorer.com permet de tester les fonctionnalités experimentales sur GCC trunk, Clang trunk ou MSVC.


Positionnement actuel

C et C++ occupent des niches spécifiques ou leurs caractéristiques sont irreplacables :

Domaine Langage préféré Exemples concrets
Noyaux d'OS C Linux, FreeBSD, Windows NT kernel
Systèmes embarqués C, C++ Firmware ARM, microcontrôleurs AVR/STM32
Moteurs de jeux C++ Unreal Engine, id Tech, proprietary AAA engines
Calcul haute performance C, C++ OpenMPI, BLAS, LAPACK, simulation physique
Navigateurs web C++ Chrome (Blink), Firefox (Gecko), Safari (WebKit)
Bases de données C, C++ PostgreSQL (C), RocksDB (C++), SQLite (C)
Compilateurs C++ LLVM/Clang, GCC, MSVC
Bibliotheques système C glibc, musl, OpenSSL, zlib

Quand éviter C/C++

Pour les services web génériques, les scripts d'automatisation, le machine learning applicatif ou les outils CLI simples, Python, Go ou Rust offrent une productivité bien supérieure avec moins de risques de vulnérabilités mémoire. C et C++ se justifient quand les performances brutes, la proximite hardware ou l'interopérabilité avec du code legacy l'imposent.