Énigme des tailles : pourquoi int et long se comportent-ils différemment selon les compilateurs ?
\n\nQuiconque a sérieusement étudié le C++ a tôt ou tard rencontré cette énigme. Vous écrivez un code simple :
\n\n#include <iostream>\n\nint main() {\n std::cout << "Taille de int : " << sizeof(int) << " octets\\n";\n std::cout << "Taille de long : " << sizeof(long) << " octets\\n";\n std::cout << "Taille de long long : " << sizeof(long long) << " octets\\n";\n return 0;\n}\n\nVous l'exécutez sur votre ordinateur portable — vous obtenez 4, 4, 8. Vous l'exécutez sur un serveur Linux — 4, 8, 8. Et sur un vieux système 16 bits (oui, ils existent encore !) — 2, 4, 8. Où est le piège ? Pourquoi le C++, un langage réputé pour sa puissance et son contrôle, permet-il une telle incertitude ?
\n\nLa réponse est à la fois simple et complexe : la norme C++ laisse délibérément les tailles des types entiers à la discrétion de l'implémentation. Ce n'est pas un bug, mais une fonctionnalité qui permet au langage de fonctionner sur n'importe quel matériel — des microcontrôleurs aux superordinateurs. Mais pour le développeur, cela signifie une chose : si vous écrivez du code portable, vous ne pouvez pas compter sur des tailles spécifiques.
\n\nVoyons ce que garantit réellement la norme C++ (de C++98 à C++23) et comment éviter le piège de la dépendance à la plateforme.
\n\nQue garantit la norme C++ ? Tailles minimales et hiérarchie
\n\nAu lieu de dire "int fait 4 octets", la norme établit des plages de valeurs minimales et une hiérarchie stricte des tailles. Voici les règles clés du projet de norme (section [basic.fundamental]) :
\n\n- \n
- Taille minimale de
char: 1 octet (8 bits, bien que formellement un octet en C++ puisse être plus grand). \n - Hiérarchie des tailles :
sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long). \n - Bits minimaux :\n
- \n
short: au moins 16 bits. \n int: au moins 16 bits. \n long: au moins 32 bits. \n long long: au moins 64 bits (ajouté en C++11). \n
\n - Taille de
int: la norme recommande queintait une "taille naturelle" pour l'architecture cible (généralement 4 octets sur les systèmes 32/64 bits). \n
Notez que long peut être égal à int (sur Windows 32 bits) ou à long long (sur Linux 64 bits). C'est parfaitement légal !
Exemple pratique : vérification sur votre système
\n\nExécutez ce code et comparez les résultats avec des collègues utilisant différents systèmes d'exploitation :
\n\n#include <iostream>\n#include <climits> // pour INT_MAX, LONG_MAX, etc.\n\nint main() {\n std::cout << "Tailles en octets :\\n";\n std::cout << "short : " << sizeof(short) << "\\n";\n std::cout << "int : " << sizeof(int) << "\\n";\n std::cout << "long : " << sizeof(long) << "\\n";\n std::cout << "long long : " << sizeof(long long) << "\\n\\n";\n\n std::cout << "Valeurs maximales :\\n";\n std::cout << "INT_MAX : " << INT_MAX << "\\n";\n std::cout << "LONG_MAX : " << LONG_MAX << "\\n";\n std::cout << "LLONG_MAX : " << LLONG_MAX << "\\n";\n return 0;\n}\n\nVous verrez que sur Windows (MSVC), long fait souvent 4 octets, tandis que sur Linux (GCC/Clang), il fait 8 octets. C'est une source classique de bugs lors du portage de code entre plateformes.
Pourquoi la norme ne fixe-t-elle pas les tailles ? Contexte historique
\n\nImaginez les années 1970. Les processeurs étaient 8 bits, 16 bits, et les 32 bits commençaient tout juste à apparaître. Les créateurs du C (et