Ajouter des variables
Stockez et récupérez des valeurs.
Ajouter des variables est une leçon C Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C Academy comprend 4 leçons au total.
Au-delà de l'arithmétique
Pour prendre en charge x = 5, puis x + 1, l'interpréteur a besoin d'identifiants et d'un endroit où stocker leurs valeurs. Cet espace de stockage est l'environnement.
Nous allons étendre l'analyseur lexical, l'analyseur syntaxique et l'évaluateur afin de gérer les noms et les affectations.
Analyser les identifiants
Un identifiant commence par une lettre ou un trait de soulignement, puis peut contenir des lettres, des chiffres ou des traits de soulignement. Nous copions le nom dans le jeton.
Un tampon de taille fixe simplifie l'exemple ; les analyseurs lexicaux réels internent les noms.
#include <ctype.h>
#include <string.h>
typedef struct { TokKind kind; int value; char name[32]; } Token;
static Token lex_ident(void) {
Token t; t.kind = TOK_IDENT; int i = 0;
while (isalnum((unsigned char)peek()) || peek() == '_')
if (i < 31) t.name[i++] = advance(); else advance();
t.name[i] = '\0';
return t;
}Un nœud de variable
L'AST acquiert deux types de nœuds : une référence de variable et une affectation. Chacun stocke le nom de la variable.
L'affectation conserve également l'expression dont elle stocke la valeur.
typedef struct Node {
enum { N_NUM, N_BINOP, N_VAR, N_ASSIGN } kind;
int value; char op; char name[32];
struct Node *left, *right; /* assign uses right as value expr */
} Node;L'environnement
L'environnement associe des noms à des valeurs. Un simple tableau linéaire de paires nom/valeur suffit pour un petit interpréteur.
Les langages plus importants utilisent des tables de hachage pour une recherche en O(1) et des portées imbriquées.
#define MAX_VARS 64
typedef struct {
char names[MAX_VARS][32];
int values[MAX_VARS];
int count;
} Env;
static Env env; /* global for this tiny example */Affecter une variable
Une affectation met soit à jour un emplacement existant, soit en ajoute un nouveau. La recherche linéaire permet de garder un code court.
Renvoyer la valeur stockée permet d'utiliser les affectations comme des expressions, par exemple y = (x = 3).
#include <string.h>
static int env_set(const char *name, int v) {
for (int i = 0; i < env.count; i++)
if (strcmp(env.names[i], name) == 0) {
env.values[i] = v; return v;
}
strcpy(env.names[env.count], name);
env.values[env.count] = v;
env.count++;
return v;
}Lire une variable
La recherche parcourt les noms et renvoie la valeur correspondante. Référencer une variable non définie constitue une erreur d'exécution.
La détecter ici permet d'afficher un message clair au lieu de renvoyer une valeur indéterminée.
#include <stdio.h>
#include <stdlib.h>
static int env_get(const char *name) {
for (int i = 0; i < env.count; i++)
if (strcmp(env.names[i], name) == 0)
return env.values[i];
fprintf(stderr, "undefined variable: %s\n", name);
exit(1);
}Analyser une affectation
L'affectation possède la priorité la plus faible et est associative à droite. Nous analysons un facteur ; s'il s'agit d'un identifiant seul suivi de =, nous construisons un nœud d'affectation.
Sinon, l'identifiant représente simplement une lecture de variable.
static Node *parse_assign(void) {
if (cur().kind == TOK_IDENT) {
char saved[32]; strcpy(saved, cur().name);
bump();
if (cur().kind == TOK_ASSIGN) {
bump();
Node *val = parse_assign();
return assign_node(saved, val);
}
return var_node(saved); /* not an assignment */
}
return parse_expr();
}Évaluer les variables
L'évaluateur acquiert deux cas. Un nœud de variable recherche son nom dans l'environnement ; un nœud d'affectation évalue son expression valeur et la stocke.
Les deux réutilisent les utilitaires env_get et env_set.
int eval(Node *n) {
switch (n->kind) {
case N_NUM: return n->value;
case N_VAR: return env_get(n->name);
case N_ASSIGN: return env_set(n->name, eval(n->right));
case N_BINOP: {
int l = eval(n->left), r = eval(n->right);
switch (n->op) {
case '+': return l + r; case '-': return l - r;
case '*': return l * r; case '/': return l / r;
}
}
}
return 0;
}Une étape fonctionnelle dans le REPL
Ce programme stocke une variable, puis la relit dans une expression — le tout par l'intermédiaire de l'environnement. Il modélise une ligne d'un véritable interpréteur.
Exécutez-le pour voir l'affectation et la recherche fonctionner ensemble.
#include <stdio.h>
#include <string.h>
#define MAX_VARS 64
static char names[MAX_VARS][32];
static int values[MAX_VARS];
static int count;
static int env_set(const char *n,int v){
for(int i=0;i<count;i++) if(!strcmp(names[i],n)){values[i]=v;return v;}
strcpy(names[count],n); values[count]=v; count++; return v;
}
static int env_get(const char *n){
for(int i=0;i<count;i++) if(!strcmp(names[i],n)) return values[i];
return 0;
}
int main(void){
env_set("x", 5); /* x = 5 */
int r = env_get("x") + 1; /* x + 1 */
printf("x = %d\n", env_get("x"));
printf("x + 1 = %d\n", r);
return 0;
}Portées et masquage
Un environnement unique et plat est global. Les langages réels ajoutent des portées imbriquées afin que les variables locales d'une fonction n'écrasent pas les noms externes.
Vous implémentez cela en chaînant les environnements : la recherche part de la portée la plus interne et remonte vers l'extérieur.
typedef struct Env {
char names[MAX_VARS][32];
int values[MAX_VARS];
int count;
struct Env *parent; /* enclosing scope */
} Env;Pour aller plus loin
Une fois les variables en place, vous pouvez ajouter des instructions, des conditionnelles et des fonctions. Chacune correspond à un nouveau type de nœud et à un cas dans eval.
À partir de là, le même pipeline analyseur lexical-analyseur syntaxique-évaluateur peut évoluer jusqu'à devenir un véritable petit langage.
Vérification rapide
Réfléchissez au rôle de l'environnement.
Récapitulatif
Vous avez ajouté les identifiants à l'analyseur lexical, les nœuds var/assign à l'AST, un environnement avec des opérations de définition et de lecture, ainsi que les cas d'évaluation pour les lectures et les affectations.
L'interpréteur mémorise maintenant un état — la base nécessaire aux instructions et aux fonctions.
Questions Fréquemment Posées
La leçon « Ajouter des variables » est-elle gratuite ?
Oui — le texte complet de « Ajouter des variables » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C Academy, passe à CoddyKit PRO. Le cours C Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Ajouter des variables » ?
Stockez et récupérez des valeurs. Tu pratiques C Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C Academy ?
Aucune expérience préalable n'est requise. C Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Ajouter des variables » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C Academy ?
Oui. Chaque leçon C Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Découper l’entrée en jetons
- Analyser des expressions
- Évaluer l’arbre
- Ajouter des variables