C-2.1 Pointers
ทุกตัวแปรมี 3 สิ่ง: ชื่อ, ค่า, และ address — pointer คือตัวแปรที่เก็บ address ของตัวแปรอื่น ฟังดูนามธรรม แต่นี่คือสิ่งที่ซ่อนอยู่ใต้ทุก reference, foreign key, และ cell reference ที่คุณเคยใช้
ทำไมต้องรู้เรื่อง Pointer?
Section titled “ทำไมต้องรู้เรื่อง Pointer?”ลองคิดแบบนี้ — คุณมีหนังสือ 1 เล่มอยู่บนชั้น:
- ค่า = เนื้อหาในหนังสือ
- Address = ตำแหน่งบนชั้น (แถว 3, ช่อง 7)
- Pointer = กระดาษโน้ตที่เขียนว่า “ดูแถว 3 ช่อง 7”
แทนที่จะ copy หนังสือทั้งเล่ม คุณแค่ส่งกระดาษโน้ต — นี่คือ pointer
& และ * — สอง operators ที่สำคัญที่สุด
Section titled “& และ * — สอง operators ที่สำคัญที่สุด”| Operator | ชื่อ | ทำอะไร | อ่านว่า |
|---|---|---|---|
&x | address-of | ให้ address ของ x | ”address ของ x” |
*p | dereference | ให้ค่าที่ address ที่ p ชี้ไป | ”ค่าที่ p ชี้ไป” |
#include <stdio.h>
int main() { int x = 42; int *p = &x; // p เก็บ address ของ x
printf("=== ตัวแปร x ===\n"); printf("ค่า (x): %d\n", x); // 42 printf("address (&x): %p\n", (void*)&x); // 0x7ffc... (address จริง) printf("size: %zu bytes\n", sizeof(x)); // 4
printf("\n=== pointer p ===\n"); printf("ค่าของ p (address ที่ชี้ไป): %p\n", (void*)p); // address ของ x printf("ค่าที่ p ชี้ไป (*p): %d\n", *p); // 42 printf("size ของ pointer: %zu bytes\n", sizeof(p)); // 8
return 0;}ผลลัพธ์ (address จะต่างในแต่ละเครื่อง):
=== ตัวแปร x ===ค่า (x): 42address (&x): 0x7ffc8a1b2c3dsize: 4 bytes
=== pointer p ===ค่าของ p (address ที่ชี้ไป): 0x7ffc8a1b2c3dค่าที่ p ชี้ไป (*p): 42size ของ pointer: 8 bytesSheets มี “pointer” อยู่แล้ว — คือ cell reference:
A1 = 42B1 = =A1 ← "pointer" ชี้ไปหาค่าใน A1C1 = =A1 * 2 ← ใช้ค่าจาก A1 ผ่าน referenceเมื่อเปลี่ยน A1 เป็น 100 → B1 และ C1 เปลี่ยนตาม เพราะมันเก็บ reference ไม่ใช่ค่า
x = 42y = x # y ชี้ไปที่ object เดียวกับ xprint(id(x)) # address ของ object (เหมือน &x ใน C)print(id(y)) # address เดียวกัน!Python ทุกตัวแปรเป็น reference (pointer) อยู่แล้ว แต่ซ่อนไว้
-- foreign key = "pointer" ชี้ไปหา row ในตารางอื่นCREATE TABLE users ( id INT PRIMARY KEY, -- "address" ของ row นี้ name VARCHAR(50));CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT REFERENCES users(id), -- pointer! amount DOUBLE PRECISION);เปลี่ยนค่าผ่าน Pointer
Section titled “เปลี่ยนค่าผ่าน Pointer”นี่คือพลังที่แท้จริงของ pointer — คุณเปลี่ยนค่าของตัวแปรโดย ไม่ต้องแตะตัวแปรตรงๆ:
#include <stdio.h>
int main() { int x = 42; int *p = &x;
printf("Before: x = %d\n", x); // 42
*p = 100; // เปลี่ยนค่าที่ p ชี้ไป = เปลี่ยน x!
printf("After: x = %d\n", x); // 100 printf(" *p = %d\n", *p); // 100
// x และ *p คือสิ่งเดียวกัน! printf("\n&x = %p\n", (void*)&x); printf("p = %p\n", (void*)p); printf("(same address!)\n");
return 0;}ผลลัพธ์:
Before: x = 42After: x = 100 *p = 100
&x = 0x7ffc8a1b2c3dp = 0x7ffc8a1b2c3d(same address!)สิ่งนี้เทียบเท่ากับ: เปลี่ยนค่าใน cell A1 แล้ว cell B1 (ที่มี =A1) เปลี่ยนตาม
เปลี่ยน A1 จาก 42 เป็น 100 → B1 (=A1) เปลี่ยนตามทันที
นี่คือ “dereference แล้วเปลี่ยนค่า” ใน Sheets
# Python lists เป็น mutable — reference ทำงานเหมือน pointerdata = [42, 99, 7]alias = data # alias ชี้ไปที่ list เดียวกันalias[0] = 100print(data[0]) # 100 — เปลี่ยนตาม!-- UPDATE ผ่าน foreign key = "เปลี่ยนค่าที่ pointer ชี้ไป"UPDATE users SET name = 'New Name' WHERE id = 1;-- ทุก order ที่ JOIN กับ user_id = 1 จะเห็นชื่อใหม่Pointer กับ String — char *
Section titled “Pointer กับ String — char *”string ใน C จริงๆ แล้วคือ pointer ไปหา char ตัวแรก ของ array:
#include <stdio.h>
int main() { char greeting[] = "HELLO"; char *s = greeting; // s ชี้ไปที่ตัวอักษรตัวแรก
printf("s points to: %p\n", (void*)s); printf("*s = '%c' (ตัวแรก)\n", *s); // H printf("*(s+1) = '%c'\n", *(s+1)); // E printf("*(s+4) = '%c'\n", *(s+4)); // O
// เดินผ่าน string ด้วย pointer printf("\n--- Walk through string ---\n"); while (*s != '\0') { printf("address %p '%c' (ASCII %d)\n", (void*)s, *s, *s); s++; // เลื่อน pointer ไปตัวถัดไป } printf("address %p '\\0' (null terminator)\n", (void*)s);
return 0;}ผลลัพธ์:
s points to: 0x7ffc8a1b2c30*s = 'H' (ตัวแรก)*(s+1) = 'E'*(s+4) = 'O'
--- Walk through string ---address 0x7ffc8a1b2c30 'H' (ASCII 72)address 0x7ffc8a1b2c31 'E' (ASCII 69)address 0x7ffc8a1b2c32 'L' (ASCII 76)address 0x7ffc8a1b2c33 'L' (ASCII 76)address 0x7ffc8a1b2c34 'O' (ASCII 79)address 0x7ffc8a1b2c35 '\0' (null terminator)สังเกต address เพิ่มขึ้นทีละ 1 — เพราะแต่ละ char ใช้ 1 byte ดังนั้น byte ถัดไปอยู่ที่ address ถัดไปพอดี
char *s = "hello" คือ pattern ที่คุณจะเห็นบ่อยที่สุดใน C — มันหมายความว่า “s เก็บ address ของตัวอักษรตัวแรก” ตัวที่เหลือเรียงต่อกันใน memory
ใน Sheets ทุก string อยู่ในเซลล์ — ไม่มีแนวคิด “pointer ไปหาตัวอักษรตัวแรก”
ใช้ =MID(A1, 1, 1) เพื่อดึงตัวอักษรทีละตัว (เหมือน *(s+0), *(s+1))
s = "HELLO"s[0] # 'H' — เหมือน *s ใน Cs[1] # 'E' — เหมือน *(s+1)# Python indexing สืบทอดมาจาก pointer arithmetic ของ CSELECT SUBSTRING('HELLO', 1, 1); -- 'H'SELECT SUBSTRING('HELLO', 2, 1); -- 'E'-- SQL เริ่มที่ 1 ไม่ใช่ 0 (ต่างจาก C/Python)| Operation | C | Sheets | Python | SQL |
|---|---|---|---|---|
| สร้าง reference | int *p = &x | =A1 | y = x | REFERENCES users(id) |
| อ่านค่าจาก reference | *p | ค่าแสดงอัตโนมัติ | ใช้ y ตรงๆ | JOIN |
| ดู address | &x / %p | ชื่อ cell “A1” | id(x) | primary key |