Il existe trois types de variables. Tout dépend de la manière de les déclarer et où elles sont déclarées. (Il s'agit ici, comme nous l'avons déjà évoqué, de déclaration au sens large, c'est-à-dire que ces variables, quelque soient leurs types, seront systématiquement définies). Par ailleurs, à chacune de ces variables correspondra une zone d'allocation particulière.
Les variables locales (automatiques) : Ceux sont toutes les variables qui sont déclarées à l'intérieur des fonctions ou en tant que paramètres. On dit que la portée de ces variables est la fonction. Du coup, la durée de vie est limitée à la durée de vie de la fonction. Attention, une variable locale qui n'est pas explicitement initialisée contient une valeur aléatoire (c'est ce qu'il se trouvait au préalable dans cette zone mémoire). Il peut exister des variables locales dont la durée de vie est encore plus courte. Il suffit que leurs portées soient limitées à un bloc d'instruction, comme par exemple, pour les boucles for où généralement nous déclarons une variable dans la zone d'initialisation qui gère l'index de l'itérative. Cette variable n'existe que pendant le traitement de la boucle. En dehors, elle n'est plus accessible puisqu'elle n'existe plus. La zone d'allocation de toutes les variables locales est la pile d'exécution. La pile évolue des adresses hautes vers les adresses basses (les variables locales déposées sur la pile le sont en commençant par le haut) tandis que le tas évolue des adresses basses vers les adresses hautes. Cette technique présente l'avantage que, pour une même zone de mémoire allouée à l'ensemble « pile+tas », nous pourrons avoir, selon le moment de l'exécution du programme, soit une pile importante et un tas limité, soit une pile limitée et un tas important. Une situation de dépassement de capacité de pile survient lorsque le sommet de la pile rejoint le sommet du tas.


Dans cet exemple, les variables utilisées sont déclarées dans des portées différentes. A ce sujet, la variable index est dans une portée extrêmement limitée puisqu'elle n'existe que durant la mise en œuvre de l'itérative for. Cette variable est une variable locale, elle est donc située sur la pile. Nous avons fréquemment des imbrications de portées locales (une portée à l'intérieur d'une autre portée).
La résolution de nom dans une portée locale se déroule ainsi : la portée immédiate dans laquelle le nom est utilisé est recherchée. Si la déclaration est trouvée, le nom est déterminé ; sinon, la portée englobante est examinée. Ce processus se poursuit jusqu'à ce qu'une déclaration soit trouvée ou que la portée globale soit examinée. Dans ce cas et si aucune déclaration n'est trouvée pour le nom, l'utilisation du nom provoque une erreur de compilation.
Grâce à ce système de résolution de nom, chaque portée peut définir ses variables comme elle l'entend sans se soucier du nom. Il est alors possible de déclarer plusieurs fois le même nom de variable dans des portées différentes. A cause de l'ordre dans lequel les portées sont examinées lors de la résolution de nom, une déclaration dans une portée englobante se retrouve cachée par une déclaration du même nom déclarée dans une portée imbriquée.
Dans notre exemple, nous avons effectivement déclarés deux variables i, dont la première est une variable globale et la seconde est une variable locale (Nous aurions même pu choisir une troisième variable i comme nom de compteur d'itérative au lieu d'index, puisque la portée est également différente). Du coup, au sein de la fonction, il n'est plus possible d'atteindre la variable globale puisqu'elle est cachée par la variable i locale. Si, malgré tout, nous désirons communiquer avec la variable i globale, il faut alors utiliser l'opérateur de portée « :: » . Il est évident que pour éviter ce genre de problème, il est souvent préférable de choisir des noms différents pour vos variables.
Dans un programme, nous avons quelque fois besoin d'une variable globale. Un problème se pose si notre programme est décomposé en plusieurs fichiers. En effet, nous savons que nous devons définir cette variable qu'une seule fois, sinon, nous avons une duplication de nom sur la même portée. Sa définition va donc, nécessairement, se trouver dans un des fichiers. Malheureusement, lorsque nous nous trouvons dans un autre fichier, le nom de cette variable n'est plus visible. Pour que le compilateur ne soit pas perturbé, il faut alors préciser que la variable est déjà définie mais à l'extérieur de notre fichier. Dans ce cas de figure, il faut juste faire une déclaration (sans définition) en utilisant le préfixe « extern » . Si plusieurs fichiers sont concernés par ce problème, il est alors préférable de réaliser la déclaration au sein d'un fichier en-tête ce qui permet de l'écrire qu'une seule fois.

Déclarer en local les variables propres à une fonction vous fait d'abord économiser énormément de mémoire, puisque la même zone (la pile) est utilisée pour créer les variables locales de toutes les fonctions, en sachant, qu'à un instant donné, seules quelques variables existent. Le même emplacement mémoire est donc utilisé pour de nombreuses variables différentes. Dans le cas contraire, chaque variable devrait posséder sa propre case se qui représenterait une taille plus que conséquente.
Mais surtout, en utilisant des variables locales, vous rendez les programmes plus lisibles et plus fiables en associant intimement les variables à leurs fonctions.
Parce que vous évitez ainsi qu'une variable utilisée dans une fonction ne soit malencontreusement modifiée par une autre fonction. En effet, une variable globale est publique. N'importe qui peut l'atteindre. Nous risquons donc de retrouver cette variable dans un état qui n'est pas prévu au moment où nous en avons besoin.
Cette notion de protection est fondamentale et, dans la mesure du possible, il est préférable de ne jamais utiliser de variable globale.
Malgré toutes ces remarques, une variable globale possède l'avantage de proposer la persistance. Sa durée de vie est la durée de vie du programme. Ainsi, il est possible de conserver une valeur indépendamment de la durée de vie de la fonction. Ce qui est dommage, c'est qu'elle soit publique.
Heureusement, le langage C++ propose les variables statiques qui permettent de gérer la persistance tout en ayant un statut privé. Une variable statique est une variable locale à une fonction, mais qui garde sa valeur d'une exécution à l'autre de la fonction. Elle est introduite par le préfixe static. Du coup, cette variable utilise la zone d'allocation statique au lieu d'utiliser la pile. Bien que sa valeur persiste au cours des invocations de la fonction, la visibilité de son nom reste limitée à sa portée locale.

Comme la zone d'allocation est la zone statique, cette variable est systématiquement initialisée, soit par une valeur que vous devez préciser, soit automatiquement avec la valeur 0. Cette initialisation s'effectue uniquement lorsque l'exécution du programme passe sur la déclaration la première fois.