Tutorial

C Language 101 - Pointer ชี้กันอยู่นั่นแหละ !! (EP.8)

By Arnon Puitrakul - 13 มิถุนายน 2015

C Language 101 - Pointer ชี้กันอยู่นั่นแหละ !! (EP.8)

จากเมื่อตอนที่แล้ว เราก็ได้เรียนเรื่อง Function กันไปแล้ว แต่วันนี้ของจริงเลย เรื่องนี้อาจจะค่อนข้างเข้าใจยากนิดหน่อย พยายามอ่านกันหน่อยนะ !!! วันนี้เราจะมาพูดถึงเรื่อง Pointer

Pointer คืออะไร ?

Pointer มันก็คือรูปแบบของตัวแปรแบบนึง เมื่อหลาย ๆ ตอนที่ผ่านมาเราสร้างตัวแปรเพื่อเก็บค่าอะไรก็ตามที่เราต้องการ ถ้าจะเก็บจำนวนเต็ม ก็ต้องใช้ int อะไรแบบนี้ Pointer ก็เหมือนกัน แต่ Pointer ไม่ได้เก็บตัวเลขจำนวนเต็มหรือ ทศนิยมอะไรเลย มันมีหน้าที่เก็บ Address งงกันล่ะสิ !!
ถ้าจะให้หาย งง เราจะต้องมาดูกันก่อนว่า ตัวแปรเราหน้าตาเป็นยังไง ประกอบด้วยอะไรบ้าง

  • ที่อยู่ หรือ Address ของตัวแปร ถ้าให้เปรียบก็น่าจะเหมือนกับ ที่อยู่บ้านของเราอะครับ แต่นี่เป็นที่อยู่ใน Memory ของเครื่อง วิธีเรียก Address นั่นก็คือใช้ Address Operator (&) ที่เราได้ใช้ไปแล้วตอน scanf() นั่นเอง
  • ค่า หรือ Value อันนี้คือสิ่งที่เราเรียกมันมาใช้นั่นแหละ เหมือนเราบอกว่า a = 20; 20 นั่นแหละคือค่าของ a
    อย่างที่บอกไปว่า Pointer มันก็คือตัวแปรแบบนึง เพราะฉะนั้นตัว Pointer เองนอกจากที่มันจะเก็บ Address ของคนอื่นตามที่เราต้องการแล้ว มันก็ยังมี Address เป็นของตัวเองอีกด้วยล้าาา

การสร้าง Pointer

วิธีการสร้าง Pointer เราจะใช้เครื่องหมายดอกจัน ตอนเราสร้างตัวแแปร เพื่อบ่งบอกว่ามันคือ Pointer ลองมาดูตัวอย่างกัน....

int a = 20;
int ptr_a = &a;

จากตัวอย่างด้านบน บรรทัดแรก เราสร้างตัวแปร a ให้ค่ามันเป็น 20 และบรรทัดถัดมาเป็นพระเอกของเราในวันนี้ นั่นคือ Pointer
เราสร้าง Pointer ชื่อ ptr_a ขึ้นมา และให้ค่ามันเป็น Address ของตัวแปร a โดยใช้ Address Operator แค่นี้เองล่ะ ไม่ยากเลย
อย่างที่บอกว่า Pointer ก็เป็นตัวแปรประเภทนึง เพราะฉะนั้นมันก็จะมีทั้ง Address และค่าของมัน เราสามารถเชื่อม Pointer ต่อกับ Pointer ได้ด้วย (ทำเพื่อ ?) ลองมาดูตัวอย่างกัน

int a = 20;
int *ptr_a = &a;
int **ptrOfptr_a = &ptr_a;

จากตัวอย่างด้านบนนี้ เราจะเห็นว่า เรามีตัวแปร a ที่มีค่าเป็น 20 และเราก็สร้าง Pointer ขึ้นมาใหม่ ชื่อ ptr_a เพื่อเก็บค่า Address ของ a และสุดท้าย อีกทอดนึง เราสร้าง Pointer ชื่อ ptrOfptr_a ขึ้นมาเพื่อเก็บ Address ของ ptr_a อีกรอบนึง
ถ้าเรามองมันเป็นภาพ มันก็เหมือนกับตัวแปร a ถูกเชื่อมต่ออยู่กับ Pointer ptr_a และสุดท้าย ptr_a ก็ถูก ptrOfptr_a เชื่อมอยู่ข้างหลังด้วย
Note : Data Type ของ Pointer จะต้องเป็น Type เดียวกับ ตัวแปรที่เราจะชี้ไปหาด้วยนะ เช่น ถ้าเราจะชี้ไปหา int Pointer ของเราก็ต้องประกาศเป็น int เช่นกัน

การทำงานกับ Pointer เบื้องต้น

จากที่เมื่อกี้ เรารู้วิธีการสร้างและ ให้ค่ามันเบื้องต้นกันไปแล้ว ต่อมาเรามาดูวิธีการทำงานกัน ว่ามันทำอะไรสนุก ๆ ได้บ้าง เพื่อเป็นการยกตัวอย่าง ลองดูโค๊ตข้างล่างนี้เลย

#include <stdio.h>

int main ()
{
   int a = 20;
   int *ptr_a = &a;

   printf("%p"ptr_a);
   printf("%d",*ptr_a);

   return 0;
}

เราลองมาไล่โค๊ตดูกัน ก่อนอื่น เช่นเคย ไม่รู้จะประกาศตัวแปรชื่ออะไรดี เอา a นี่แหละ ง่ายดี เราก็ประกาศตัวแปร a และให้ค่ามันเป็น 20 เช่นเคย ถัดลงมาอีก ก็เหมือนเดิมอีก เราก็สร้าง Pointer ชื่อ ptr_a และให้มันเก็บ Address ของ a ไว้ ทีนี้ล่ะครับ เราลองมาดูค่ากันเลย
ก่อนอื่น ถ้าเราเอา แค่ ptr_a ออกมาดู ผลที่ได้มันจะเป็น Address ของ a นั่นเอง (Address ของ a มันก็คือส่วน Value ของ ptr_a นั่นแหละ เพราะเราเก็บค่ามันไว้ตอนบรรทัด ที่ 6)
บรรทัดถัดมา เราอยากได้ค่าของตัวแปรที่เราชี้ไป หรือตอนนี้ก็คือค่าของ a นั่นเอง ที่เราบอกไว้คือ 20 นั่นเอง
Note : ถ้าเราต้องการค่าของ Address ตอนที่เรา printf เราจะต้องใช้ String Format เป็น %p ด้วยนะมันถึงจะออกมาเป็น Address

Pointer กับ Array

อย่างที่เราได้ทำความรู้จักกับ Array ไปกันแล้วใน EP.5 ว่า Array มันคือชุดของตัวแปร วางเรียงกันเป็นช่อง ๆ ติดกันไปเรื่อย ๆ จนหมดช่องที่เรากำหนดไว้ โดยเลข Index จะเริ่มตั้งแต่ 0 ถึง n-1 แต่เคยสงสัยมั้ยว่า ทำไมถ้า เราเรียก ชื่อของ Array เฉย ๆ โดยไม่ได้บอกเลข Index มันจะเป็นยังไง มาลองดูกันเลย

int arr [1];
printf("%p",arr);

ถ้าเห็นโค๊ตแล้วก็น่าจะเอ๊ะใจแล้วนะว่า อ้าว Array มันก็คือ Pointer ตัวนึงนี่หว่า ใช่ครับ มันคือ Pointer ที่ชี้ไปที่ช่องแรกของ ตัว Array แล้วถามว่า แล้วช่องที่เหลือล่ะ
เราสามารถที่จะเข้าถึง ช่องที่เหลือได้ หรือเข้าถึงช่องไหนก็ได้ใน Array ด้วย Operator บวก ลบ คูณ และหาร ได้ด้วยล่ะ
ถ้าถามว่า ทำไม ให้เรานึกภาพ Array ก่อนว่า Array ทั้งก้อน ก็เป็นก้อนสี่เหลี่ยมก้อนนึง แล้วข้างในถูกซอยย่อยเป็นห้อง ๆ ตามจำนวน Member ที่เราประกาศไว้ สมมุติว่า Address ของตัวที่ 0 คือ 100 แล้วถ้ามันเป็น int แล้ว เพราะฉะนั้นช่องถัดไปควรจะเป็น 102 ใช่มั้ยครับ เพราะว่า 100 + 2 = 102 ไงล้าา นอกจากบวกแล้ว เรายัง ลบ คูณ หาร ได้อีกด้วย ก็ใช้หลักการเดียวกัน
แต่ตัวภาษา C มันทำให้เราง่ายกว่านั้นอีก อย่างที่เมื่อกี้ ถ้าเราจะเข้าถึง Member ของ Array ที่เป็น int ไปอีกช่อง เราจะต้อง มานึกอีกว่า int ตัวนึงมันเท่าไหร่กันน้าา ฉะนั้นใน C เราไม่จำเป็นต้องบอกว่า เราจะเลื่อนไปกี่ bit กี่ byte แค่บอกว่า เราจะเลื่อนไปกี่ช่อง เช่น ตัวอย่างเมื่อกี้ เราจะเข้าถึง Member ช่องถัดไปของ Array ที่เป็น int ไป 1 ช่อง เราก็แค่บอกมันว่า +1 ได้เลย เช่น

int a [] = {1,2,3,4,5};
int ptr_a = a;
printf("%d ",*ptr_a);
ptr_a++;
printf("%d",*ptr_a);

ก่อนอื่นก็ลองสร้าง Array ชื่อ a ขึ้นมาก่อน ถัดมาเราก็สร้าง Pointer พระเอกของเรา ชื่อว่า ptr_a แล้วให้มันเท่ากับ a ตรง ๆ เลย และลอง printf() ออกมาทางหน้าจอ จากนั้นเราบวกค่าของ ptr_a ไปอีก 1 หรือนั่นก็คือการขยับไป 1 ช่อง Member ของ Array หรือนั่นก็คือการบวก 2 ใน Address นั่นเอง แล้วอีกรอบ เราลอง printf() ออกมาดู เพื่อเช็คว่ามันขยับตามที่เราคิดไว้มั้ย
Output ที่ออกมาก็คือ 1 2 ซึ่งตรงตามที่เราต้องการเลย
เรามีทางเลือกให้ ในบรรทัดที่ 2 เราสามารถเขียนอีกแบบนึงได้

int ptr_a = a[0];

แต่จะเขียนแบบแรกก็ได้เช่นกัน แต่แนะนำแบบแรกจะดีกว่านะ
สรุปนะครับ Pointer ถือว่าเป็นเรื่องที่ค่อนข้างจะต้องใช้ความเข้าใจมากหน่อย เพราะมันค่อนข้างมีรายละเอียดเยอะมากเลยล่ะ แต่ถ้าได้ลองเล่นจริง ๆ แล้วเราจะรู้เลยว่า Pointer มันทำให้เรา ทำอะไรได้เยอะขึ้น และง่ายขึ้นเยอะมาก ๆ เลยล่ะ วันนี้ก็พอแค่นี้ก่อนล่ะกัน เดี๋ยวเยอะไปเน้อ ไว้เจอกันตอนหน้า เขียนโค๊ตในสนุกนะครับ วันนี้สวัสดีครับ

Read Next...

จัดการ Docker Container ง่าย ๆ ด้วย Portainer

จัดการ Docker Container ง่าย ๆ ด้วย Portainer

การใช้ Docker CLI ในการจัดการ Container เป็นท่าที่เราใช้งานกันทั่วไป มันมีความยุ่งยาก และผิดพลาดได้ง่ายยังไม่นับว่ามี Instance หลายตัว ทำให้เราต้องค่อย ๆ SSH เข้าไปทำทีละตัว มันจะดีกว่ามั้ย หากเรามี Centralised Container Managment ที่มี Web GUI ให้เราด้วย วันนี้เราจะพาไปทำความรู้จักกับ Portainer กัน...

Host Website จากบ้านด้วย Cloudflare Tunnel ใน 10 นาที

Host Website จากบ้านด้วย Cloudflare Tunnel ใน 10 นาที

ปกติหากเราต้องการจะเปิดเว็บสักเว็บ เราจำเป็นต้องมี Web Server ตั้งอยู่ที่ไหนสักที่หนึ่ง ต้องใช้ค่าใช้จ่าย พร้อมกับต้องจัดการเรื่องความปลอดภัยอีก วันนี้เราจะมาแนะนำวิธีการที่ง่ายแสนง่าย ปลอดภัย และฟรี กับ Cloudflare Tunnel ให้อ่านกัน...

จัดการข้อมูลบน Pandas ยังไงให้เร็ว 1000x ด้วย Vectorisation

จัดการข้อมูลบน Pandas ยังไงให้เร็ว 1000x ด้วย Vectorisation

เวลาเราทำงานกับข้อมูลอย่าง Pandas DataFrame หนึ่งในงานที่เราเขียนลงไปให้มันทำคือ การ Apply Function เข้าไป ถ้าข้อมูลมีขนาดเล็ก มันไม่มีปัญหาเท่าไหร่ แต่ถ้าข้อมูลของเราใหญ่ มันอีกเรื่องเลย ถ้าเราจะเขียนให้เร็วที่สุด เราจะทำได้โดยวิธีใดบ้าง วันนี้เรามาดูกัน...

ปั่นความเร็ว Python Script เกือบ 700 เท่าด้วย JIT บน Numba

ปั่นความเร็ว Python Script เกือบ 700 เท่าด้วย JIT บน Numba

Python เป็นภาษาที่เราใช้งานกันเยอะมาก ๆ เพราะความยืดหยุ่นของมัน แต่ปัญหาของมันก็เกิดจากข้อดีของมันนี่แหละ ทำให้เมื่อเราต้องการ Performance แต่ถ้าเราจะบอกว่า เราสามารถทำได้ดีทั้งคู่เลยละ จะเป็นยังไง เราขอแนะนำ Numba ที่ใช้งาน JIT บอกเลยว่า เร็วขึ้นแบบ 700 เท่าตอนที่ทดลองกันเลย...