เพิ่มตัวแปร
จัดเก็บและเรียกคืนค่า
เพิ่มตัวแปร เป็นบทเรียน C Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
ก้าวข้ามการคำนวณเลขคณิต
เพื่อรองรับ x = 5 และต่อมาคือ x + 1 ตัวแปลผลจำเป็นต้องมี ตัวระบุ และที่เก็บค่าสำหรับตัวระบุเหล่านั้น ที่เก็บนี้เรียกว่าสภาพแวดล้อม
เราจะขยายตัววิเคราะห์คำศัพท์ ตัวแยกวิเคราะห์ และตัวประเมินผล เพื่อจัดการชื่อและการกำหนดค่า
การวิเคราะห์คำศัพท์ของตัวระบุ
ตัวระบุเริ่มต้นด้วยตัวอักษรหรือขีดล่าง และต่อด้วยตัวอักษร ตัวเลข หรือขีดล่าง เราจะคัดลอกชื่อลงในโทเค็น
บัฟเฟอร์ขนาดคงที่ทำให้ตัวอย่างเรียบง่าย ส่วนตัววิเคราะห์คำศัพท์จริงจะเก็บชื่อไว้ในตารางร่วม
#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;
}โหนดตัวแปร
AST จะมีชนิดโหนดเพิ่มขึ้นสองชนิด ได้แก่ การอ้างอิงตัวแปรและการกำหนดค่า แต่ละชนิดจะเก็บชื่อตัวแปรไว้
การกำหนดค่ายังเก็บนิพจน์ที่ให้ค่าซึ่งจะถูกจัดเก็บด้วย
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;สภาพแวดล้อม
สภาพแวดล้อมจะจับคู่ชื่อกับค่า อาร์เรย์แบบเชิงเส้นอย่างง่ายของคู่ชื่อ/ค่าก็เพียงพอสำหรับตัวแปลผลขนาดเล็ก
ภาษาขนาดใหญ่ใช้ตารางแฮชเพื่อค้นหาในเวลา O(1) และรองรับขอบเขตตัวแปรที่ซ้อนกัน
#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 */การกำหนดค่าตัวแปร
การกำหนดค่าอาจอัปเดตช่องที่มีอยู่ หรือเพิ่มช่องใหม่ต่อท้าย การค้นหาแบบเชิงเส้นช่วยให้โค้ดสั้น
การคืนค่าที่จัดเก็บไว้ทำให้สามารถใช้การกำหนดค่าเป็นนิพจน์ได้ เช่น 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;
}การอ่านค่าตัวแปร
การค้นหาจะสแกนหาชื่อแล้วคืนค่าของชื่อนั้น การอ้างอิงตัวแปรที่ไม่ได้กำหนดค่าถือเป็นข้อผิดพลาดขณะทำงาน
การตรวจจับกรณีนี้ตรงจุดดังกล่าวทำให้ได้ข้อความที่ชัดเจน แทนที่จะคืนค่าขยะ
#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);
}การแยกวิเคราะห์การกำหนดค่า
การกำหนดค่ามีลำดับความสำคัญต่ำที่สุดและจับกลุ่มจากขวาไปซ้าย เราจะแยกวิเคราะห์ตัวประกอบก่อน หากเป็นตัวระบุเดี่ยวที่ตามด้วย = เราจะสร้าง assign node
มิฉะนั้น ตัวระบุนั้นก็เป็นเพียงการอ่านค่าตัวแปร
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();
}การประเมินผลตัวแปร
ตัวประเมินผลจะมีกรณีเพิ่มขึ้นสองกรณี โหนดตัวแปรจะค้นหาชื่อในสภาพแวดล้อม ส่วน assign node จะประเมินนิพจน์ค่าของตัวเองแล้วจัดเก็บค่านั้น
ทั้งสองกรณีใช้ตัวช่วย env_get และ 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;
}ขั้นตอนหนึ่งของ REPL ที่ทำงานได้
โปรแกรมนี้จัดเก็บตัวแปร แล้วอ่านตัวแปรนั้นกลับมาในนิพจน์ โดยทำงานผ่านสภาพแวดล้อมทั้งหมด เป็นแบบจำลองของหนึ่งบรรทัดในตัวแปลผลจริง
เรียกใช้เพื่อดูการทำงานร่วมกันของการกำหนดค่าและการค้นหา
#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;
}ขอบเขตตัวแปรและการบดบังชื่อ
สภาพแวดล้อมแบบแบนเพียงหนึ่งเดียวถือเป็นระดับโกลบอล ภาษาจริงเพิ่มขอบเขตตัวแปรที่ซ้อนกัน เพื่อไม่ให้ตัวแปรภายในฟังก์ชันเขียนทับชื่อด้านนอก
คุณจะทำเช่นนี้ได้โดยเชื่อมสภาพแวดล้อมเข้าด้วยกัน การค้นหาจะเดินจากขอบเขตด้านในสุดออกไปด้านนอก
typedef struct Env {
char names[MAX_VARS][32];
int values[MAX_VARS];
int count;
struct Env *parent; /* enclosing scope */
} Env;ขั้นต่อไป
เมื่อมีตัวแปรแล้ว คุณสามารถเพิ่มคำสั่ง เงื่อนไข และฟังก์ชันได้ แต่ละอย่างคือชนิดโหนดใหม่พร้อมกรณีการประเมินผล
จากจุดนี้ กระบวนการตัววิเคราะห์คำศัพท์-ตัวแยกวิเคราะห์-ตัวประเมินผลแบบเดิมสามารถขยายไปเป็นภาษาขนาดเล็กที่ใช้งานได้จริง
ตรวจสอบความเข้าใจ
ลองคิดว่าสภาพแวดล้อมมีหน้าที่รับผิดชอบอะไร
สรุปทบทวน
คุณได้เพิ่มตัวระบุให้ตัววิเคราะห์คำศัพท์ เพิ่มโหนด var/assign ให้ AST เพิ่มสภาพแวดล้อมที่มีการกำหนดค่าและการอ่านค่า รวมถึงเพิ่มกรณีการประเมินผลสำหรับการอ่านและการกำหนดค่า
ตอนนี้ตัวแปลผลจดจำสถานะได้แล้ว ซึ่งเป็นพื้นฐานสำหรับคำสั่งและฟังก์ชัน
คำถามที่พบบ่อย
บทเรียน “เพิ่มตัวแปร” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เพิ่มตัวแปร” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เพิ่มตัวแปร”
จัดเก็บและเรียกคืนค่า คุณปฏิบัติ C Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “เพิ่มตัวแปร” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C Academy นี้ได้ไหม
ได้ บทเรียน C Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ