Adding Variables
Store and recall values.
Adding Variables is a free C Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, and your progress syncs across the web and the CoddyKit app. The C Academy course includes 4 lessons in total.
Beyond Arithmetic
To support x = 5 and later x + 1, the interpreter needs identifiers and a place to store their values. That store is the environment.
We will extend the lexer, parser, and evaluator to handle names and assignment.
Lexing Identifiers
An identifier starts with a letter or underscore and continues with letters, digits, or underscores. We copy the name into the token.
A fixed-size buffer keeps the example simple; real lexers intern names.
#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;
}A Variable Node
The AST gains two node kinds: a variable reference and an assignment. Each stores the variable name.
Assignment also keeps the expression whose value it stores.
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;The Environment
The environment maps names to values. A simple linear array of name/value pairs suffices for a small interpreter.
Larger languages use hash tables for O(1) lookup and nested scopes.
#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 */Setting a Variable
Assigning either updates an existing slot or appends a new one. Linear search keeps the code short.
Returning the stored value lets assignments be used as expressions, like 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;
}Reading a Variable
Lookup scans for the name and returns its value. Referencing an undefined variable is a runtime error.
Catching this here gives a clear message instead of returning a garbage value.
#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);
}Parsing Assignment
Assignment has the lowest precedence and is right-associative. We parse a factor; if it is a bare identifier followed by =, we build an assign node.
Otherwise the identifier is just a variable read.
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();
}Evaluating Variables
The evaluator gains two cases. A variable node looks its name up in the environment; an assign node evaluates its value expression and stores it.
Both reuse the env_get and env_set helpers.
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;
}A Working REPL Step
This program stores a variable, then reads it back in an expression — all through the environment. It models one line of a real interpreter.
Run it to see assignment and lookup cooperate.
#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;
}Scopes and Shadowing
A single flat environment is global. Real languages add nested scopes so a function's locals do not clobber outer names.
You implement this by chaining environments: lookup walks from the innermost scope outward.
typedef struct Env {
char names[MAX_VARS][32];
int values[MAX_VARS];
int count;
struct Env *parent; /* enclosing scope */
} Env;Where to Go Next
With variables in place you can add statements, conditionals, and functions. Each is a new node kind plus an eval case.
From here, the same lexer-parser-evaluator pipeline scales into a real little language.
Quick Check
Think about what the environment is responsible for.
Recap
You added identifiers to the lexer, var/assign nodes to the AST, an environment with set and get, and eval cases for reads and assignments.
The interpreter now remembers state — the foundation for statements and functions.
Learn C with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 39
- Lessons
- 144
Frequently Asked Questions
Is the “Adding Variables” lesson free?
Yes — the full text of “Adding Variables” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO. The C Academy course includes 4 lessons in total.
What will I learn in “Adding Variables”?
Store and recall values. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C Academy?
No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
How long does the “Adding Variables” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C Academy lesson?
Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Tokenizing Input
- Parsing Expressions
- Evaluating the Tree
- Adding Variables