Variablen hinzufügen
Speichern und lesen Sie Werte.
Variablen hinzufügen ist eine kostenlose C Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C Academy-Kurs umfasst insgesamt 4 Lektionen.
Über die Arithmetik hinaus
Um x = 5 und später x + 1 zu unterstützen, benötigt der Interpreter Bezeichner und einen Ort, an dem ihre Werte gespeichert werden. Dieser Speicher ist die Umgebung.
Wir erweitern den Lexer, den Parser und den Auswerter, damit sie Namen und Zuweisungen verarbeiten können.
Bezeichner lexen
Ein Bezeichner beginnt mit einem Buchstaben oder Unterstrich und wird mit Buchstaben, Ziffern oder Unterstrichen fortgesetzt. Wir kopieren den Namen in das Token.
Ein Puffer fester Größe hält das Beispiel einfach; echte Lexer internieren Namen.
#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;
}Ein Variablenknoten
Der AST erhält zwei Knotentypen: eine Variablenreferenz und eine Zuweisung. Beide speichern den Variablennamen.
Eine Zuweisung speichert außerdem den Ausdruck, dessen Wert sie ablegt.
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;Die Umgebung
Die Umgebung ordnet Namen Werte zu. Für einen kleinen Interpreter genügt ein einfaches lineares Array aus Name-Wert-Paaren.
Größere Sprachen verwenden Hash-Tabellen für Zugriffe in O(1) und verschachtelte Gültigkeitsbereiche.
#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 */Eine Variable setzen
Eine Zuweisung aktualisiert entweder einen vorhandenen Eintrag oder fügt einen neuen hinzu. Die lineare Suche hält den Code kurz.
Wenn der gespeicherte Wert zurückgegeben wird, können Zuweisungen als Ausdrücke verwendet werden, etwa 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;
}Eine Variable lesen
Bei der Suche wird nach dem Namen gesucht und sein Wert zurückgegeben. Die Verwendung einer nicht definierten Variable ist ein Laufzeitfehler.
Wenn Sie diesen Fall hier abfangen, erhalten Sie eine klare Meldung, statt einen beliebigen Wert zurückzugeben.
#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);
}Eine Zuweisung parsen
Eine Zuweisung hat den niedrigsten Vorrang und ist rechtsassoziativ. Wir parsen einen Factor. Wenn es sich um einen allein stehenden Bezeichner gefolgt von = handelt, erzeugen wir einen Assign-Knoten.
Andernfalls wird der Bezeichner einfach gelesen.
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();
}Variablen auswerten
Der Auswerter erhält zwei Fälle. Ein Variablenknoten sucht seinen Namen in der Umgebung; ein Assign-Knoten wertet seinen Wertausdruck aus und speichert ihn.
Beide verwenden die Hilfsfunktionen env_get und env_set erneut.
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;
}Ein funktionierender REPL-Schritt
Dieses Programm speichert eine Variable und liest sie anschließend in einem Ausdruck wieder aus – alles über die Umgebung. Es bildet eine Zeile eines echten Interpreters nach.
Führen Sie es aus, um zu sehen, wie Zuweisung und Suche zusammenspielen.
#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;
}Gültigkeitsbereiche und Überlagerung
Eine einzige flache Umgebung ist global. Echte Sprachen fügen verschachtelte Gültigkeitsbereiche hinzu, damit lokale Variablen einer Funktion keine äußeren Namen überschreiben.
Sie implementieren dies, indem Sie Umgebungen verketten: Die Suche geht vom innersten Gültigkeitsbereich nach außen.
typedef struct Env {
char names[MAX_VARS][32];
int values[MAX_VARS];
int count;
struct Env *parent; /* enclosing scope */
} Env;Wie es weitergeht
Nachdem Variablen vorhanden sind, können Sie Anweisungen, Bedingungen und Funktionen hinzufügen. Jede davon ist ein neuer Knotentyp mit einem eigenen eval-Fall.
Von hier aus lässt sich dieselbe Lexer-Parser-Auswerter-Pipeline zu einer echten kleinen Sprache erweitern.
Schnelltest
Überlegen Sie, wofür die Umgebung zuständig ist.
Zusammenfassung
Sie haben dem Lexer Bezeichner hinzugefügt, dem AST Var- und Assign-Knoten, eine Umgebung mit set und get sowie eval-Fälle für Lesezugriffe und Zuweisungen.
Der Interpreter merkt sich nun seinen Zustand – die Grundlage für Anweisungen und Funktionen.
Häufig gestellte Fragen
Ist die Lektion „Variablen hinzufügen“ kostenlos?
Ja — der vollständige Text von „Variablen hinzufügen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Variablen hinzufügen“?
Speichern und lesen Sie Werte. Du übst C Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um C Academy zu starten?
Keine Vorkenntnisse erforderlich. C Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Variablen hinzufügen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser C Academy-Lektion Code schreiben und ausführen?
Ja. Jede C Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Eingaben tokenisieren
- Ausdrücke parsen
- Den Baum auswerten
- Variablen hinzufügen