พอยน์เตอร์

8 September 2015

พอยน์เตอร์ เป็นตัวแปรที่ใช้เก็บตำแหน่งที่อยู่ของตัวแปร การใช้พอยน์เตอร์ เราสามารถเข้าถึงข้อมูลที่เราต้องการได้โดยตรงโดยการใช้ชื่อของตัวแปร และมันมีประโยชน์มากในการเขียนโปรแกรมด้วยภาษาที่สามารถจัดการหน่วยความจำได้ง่าย เช่น ภาษา C และภาษา C++

มีเครื่องหมายประมาณ 2-3 อันที่คุณจะต้องรู้เกี่ยวกับพอยน์เตอร์:

  • Address-of operator (&)
  • Dereference operator (*)
  • Declaration operator (*)

Address-of operator (&)

การใช้เครื่องหมาย ampersand (&) นำหน้าชื่อของตัวแปรจะส่งค่าที่อยู่ของหน่วยความจำกลับมา ที่อยู่ของหน่วยความจำนั้นสามารถได้มาในตอนที่โปรแกรมรันเท่านั้น มันบอกได้ว่าตัวแปรนั้นอยู่ที่ไหนในหน่วยความจำ สำหรับตัวอย่าง:

&myNumber;

คำสั่งนี้จะส่งค่าที่อยู่ของหน่วยความจำกลับมาที่จะแสดงในเลขฐาน 16 แต่ในบทเรียนนี้ ตัวอย่างของเราจะใช้เลขฐาน 10 เพื่อให้ง่ายต่อความเข้าใจของคุณ

int myNumber = 10;
cout << &myNumber;   // assume to be 1477

สมมติคำสั่งด้านบนจะแสดง 1477 ออกทางหน้าจอ นั่นหมายถึงตัวแปร myNumber มีตำแหน่งในหน่วยความจำคือ 1477 (physical address) ดังนั้น เราสามารถเข้าถึงข้อมูลของ myNumber ได้โดยตรงโดยการใช้หลายเลขที่อยู่ 1477

Dereference operator (*)

ในตัวอย่างก่อนหน้า ที่อยู่ของตัวแปรสามารถได้มาจากเครื่องหมาย ampersand ก่อนชื่อตัวแปร ในการที่จะเข้าถึงข้อมูลโดยการใช้ที่อยู่เหล่านี้ เราใช้ *myNumber เพื่อที่จะรับค่า

int myNumber = 10;
foo1 = &myNumber;   // 1477
foo2 = *foo1 ;

ในตัวอย่างนี้ แสดงให้คุณเห็นถึงวิธีการเข้าถึงข้อมูลเมื่อเรารู้ที่อยู่ของมัน เราสมมติ 1477 เป็นที่อยู่ myNumber เพราะว่าในความเป็นจริง เราไม่มีทางรู้ที่อยู่จริงๆ จนกว่าโปรแกรมจะรัน foo1 เก็บที่อยูของตัวแปร myNumber (1477) ได้รับค่าที่ตัวแปร foo1 ชี้ไปโดยการใช้ *foo1 และมันจะส่งค่า 10 กลับมายังตัวแปร foo2

Declaring pointers

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

int *pointer;
float *p1;
double *p2;

ในตัวอย่าง เราได้สร้างตัวแปรพอยน์เตอร์ 3 ตัว การสร้างพอยน์เตอร์จะต้องเริ่มด้วยการประกาศประเภทของมัน เช่น (int, float, double) ประเภทที่ว่านี้ไม่ได้หมายถึงประเภทของพอยน์เตอร์ แต่มันหมายถึงประเภทของตัวแปรที่พอยน์เตอร์จะชี้ไป และตามด้วยชื่อของพอยน์เตอร์ และคุณจะเห็นว่าเราได้ใส่เครื่องหมาย star (*) นำหน้าก่อนชื่อของมัน คุณอย่าสับสนในเครื่องหมาย deference operator (*) ที่มันใช้ในการเข้าถึงข้อมูลที่พอยน์เตอร์ได้ชี้ไป ซึ่งมันมีความหมายที่แตกต่างกันอย่างที่ได้กล่าวไป

#include <iostream>
using namespace std;

int main()
{
    int myvar = 10;
    int *mypointer;
    mypointer = &myvar;
    *mypointer = 20;
    cout << myvar;
    return 0;
}

เมื่อเรารันโปรแกรมนี้ มันจะได้ผลลัพธ์ดังนี้

20

ในตัวอย่างนี้ เราได้สร้างพอยน์เตอร์ที่ชื่อว่า mypointer และประเภทของมันคือ int เพราะว่าเราต้องการที่จะใช้ตัวแปรพอยน์เตอร์นี้ไปยังตัวแปร myvay ซึ่งเป็นตัวแปรประเภทแบบ integer และคำสั่ง mypointer = &myvar เราให้พอยน์เตอร์ของเราชี้ไปที่ตำแหน่งที่อยู่ของ myvar ตอนนี้ เราสามารถทำทุกอย่างเกี่ยวกับที่อยู่ของตัวแปรพอยน์เตอร์ mypointer ดังนั้นเราได้กำหนดค่า 20 ไปยังตำแหน่งนั้น และสุดท้าย เราแสดงผล myvar เพื่อดูผลลัพธ์ของมัน

Pointers และ arrays

การใช้พอยน์เตอร์กับอาเรย์นั้นเป็นสิ่งที่มีประโยชน์มาก เพราะว่าเรารู้ว่าตำแหน่งของข้อมูลในอาเรย์นั้นอ้างอิงกับตำแหน่งแรกของอาเรย์

#include <iostream>
using namespace std;

int main()
{
    int mynum[5] = {10, 20, 30, 40, 50};
    int *mypoint;
    mypoint = mynum;
    *mypoint = 20;
    mypoint++;
    *mypoint = 80;
    mypoint = mynum;
    mypoint += 4;
    *mypoint = 100;

    for (int i = 0; i < 5; i++)
    {
        cout << mynum[i] << ", ";
    }
    return 0;
}
20, 80, 30, 40, 100,

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

Pointers addresses

พอนย์เตอร์นั้นเก็บค่าที่อยู่ของ Memory ที่ข้อมูลนั้นถูกเก็บอยู่ ในการที่จะดูตำแหน่งที่ข้อมูลถูกเก็บอยู่ สามารถดูได้สองวิธี คือผ่านตัวแปรพอยน์เตอร์ หรือผ่านสัญลักษณ์ของ Memory address (&) มาดูตัวอย่าง

#include <iostream>
using namespace std;

int main()
{
    int mynum[5] = {10, 20, 30, 40, 50};
    int *mypoint = mynum;

    // via point
    for (int i = 0; i < 5; i++)
    {
        cout <<  "Address at " << i << " = " << mypoint << endl;
        mypoint++;
    }
    cout << endl;

    // via addressing symbol
    for (int i = 0; i < 5; i++)
    {
        cout <<  "Address at " << i << " = " << &mynum[i] << endl;
    }

    return 0;
}

และนี่เป็นผลลัพธ์เมื่อรันโปรแกรม โดยทั้งสองจะได้ผลลัพธ์เหมือนกัน

Address at 0 = 0x28fed0
Address at 1 = 0x28fed4
Address at 2 = 0x28fed8
Address at 3 = 0x28fedc
Address at 4 = 0x28fee0

Address at 0 = 0x28fed0
Address at 1 = 0x28fed4
Address at 2 = 0x28fed8
Address at 3 = 0x28fedc
Address at 4 = 0x28fee0

Pointer arithmetics

ในพอยน์เตอร์ ภาษา C++ ให้เราสามารถกระทำการทางคณิตศาสตร์กับตัวแปรพอยน์เตอร์ได้ ที่เราเพิ่งจะทำกันคือการทำให้พอยน์เตอร์ชี้ไปที่ที่อยู่ของตัวแปร มาดูตัวอย่างของพอยน์เตอร์กับการดำเนินการทางคณิตศาสตร์

int number = 8; // address 1277
int *p;
p = &number;
p++; // 1278
p--; // 1277
p+=1000; // 2277

int *p2;
p2 = &number;
*p2++;   // number = 9

มาสมมติว่าเรามีตัวแปร number ซึ่งที่ตำแหน่งที่อยู่ที่ 1277 และเราใช้พอยน์เตอร์ p ชี้ไปที่ 1277 (Number's address) หลังจากนั้นเราสามารถย้ายพอยน์เตอร์ไปยังที่ไหนก็ตามที่เราต้องการ โดยอ้างอิงตำแหน่งจาก 1277 และเราใช้ p2 เพื่อเปลี่ยนค่าของ number

ในบทนี้ เราได้ครอบคลุมพื้นฐานในเรื่องพอยน์เตอร์ ซึ่งมันมีประโยชน์ในการจัดการหน่วยความจำแบบไดนามิกส์ ที่เราจะเรียนในบทถัดไป

บทความนี้เป็นประโยชน์หรือไม่?Yes·No