ตอนที่ 7: พอยน์เตอร์ และการจองหน่วยความจำ

. . . . . . . .วันนี้เป็นเรื่อง pointer ซึ่งไม่ยากแน่นอน เพียงจำไว้ว่า pointer คือตัวชี้ นะครับง่ายๆ แบบนี้
#include <stdio.h>

#include <conio.h>

int main( )

{

int *pointer1; //<----- วิธีกำหนดตัวแปร พอยน์เตอร์

int value1 = 10; //<---- กำหนดตัวแปรแบบ Integer ให้ค่า 10

pointer1 = &value1; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 10

printf( "%i", value1 ); //<--- พิมพ์ค่า value1

printf( "%i", (int)(*pointer1) ); //<--- พิมพ์ค่าที่ชี้ไปยังตำแหน่งนั้น

return 0;

}

10

10

. . . . . . . .จากตัวอย่างข้างบนมันทำงานดังนี้ครับ การกำหนดตัวแปรแบบ pointer ต้องมีเครื่องหมายดอกจัน นำหน้าตัวแปรนั้น และวิธีการชี้ไปยังตำแหน่งที่ต้องการ ให้ทำแบบนี้

pointer1 = &value1; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 10

เครื่องหมาย & คือบอกว่าตัวแปรนั้นอยู่ตำแหน่งใดในหน่วยความจำ แต่การให้ค่า pointer1 ต้องใช้แบบนี้

*pointer1 = 10; //<--- ให้ค่า pointer1 ไม่ใช่การให้ตำแหน่งที่อ้างถึง

จากข้างบนเมื่อเราให้ค่า *pointer1 = 10 ตัวแปร value1 ก็จะมีค่าเท่ากับ 10 เหมือนกัน เพราะว่าเราอ้างถึงตำแหน่ง ที่เก็บค่าสิบตัวเดียวกัน ก็ง่ายๆ ว่า ตัวแปร pointer มีหน้าที่ชี้ตำแหน่งแค่นั้นเอง และเราสามารถแก้ไข ตำแหน่งนั้นได้เลย เพราะมันเป็นที่เดียวกัน ประโยชน์ของมันมีมากเลยละ และการใช้ค่าที่พอยน์เตอร์ชี้ไปนั้น ต้องกำหนดรูปแบบให้มันด้วยว่าเป็นข้อมูลแบบไหน เช่น

#include <stdio.h>

#include <conio.h>

#include <string.h>

int main( )

{

int *pointer1; //<----- วิธีกำหนดตัวแปร พอยน์เตอร์

int value1 = 10; //<---- กำหนดตัวแปรแบบ Integer ให้ค่า 10

int value2 = 20; //<---- กำหนดตัวแปรแบบ Integer ให้ค่า 20

pointer1 = &value1; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 10

printf( "%i", value1 ); //<--- พิมพ์ค่า value1

printf( "%i", (int)(*pointer1) ); //<--- พิมพ์ค่าที่ชี้ไปยังตำแหน่งนั้น

pointer1 = &value2; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 10

printf( "%i", (int)(*pointer1) ); //<--- พิมพ์ค่าที่ชี้ไปยังตำแหน่งนั้น

return 0;

}

10

10

20

. . . . . . . .ใครกำลังงง ลองดูตัวอย่างซ้ำๆ นะครับ เพราะเห็นแล้วจะอ๋อ.........จากตัวอย่างข้างบน pointer ตัวเดียวแต่อ้างตำแหน่งข้อมูลได้ 2 ที่ แบบนี้

pointer1 = &value1; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 10

เมื่อพิมพ์ค่าที่ pointer1 ชี้ไปก็จะพิมพ์ค่า 10 ออกมาและ

pointer1 = &value2; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 20

เมื่อพิมพ์ค่าที่ pointer1 ชี้ไปก็จะพิมพ์ค่า 20 ออกมา ก็แค่การอ้างถึงตำแหน่งข้อมูลเฉยๆ ไม่ยากๆ สามารถกำหนดตัวแปร pointer ได้หลายแบบลองดูนะครับ

printf( "%i", (int)(*pointer1) ); //<--- พิมพ์ค่าที่ชี้ไปยังตำแหน่งนั้น เป็น Interger

printf( "%i", (long)(*pointer1) ); //<--- พิมพ์ค่าที่ชี้ไปยังตำแหน่งนั้น เป็น long

อย่าใช้ผิดแบบ คือชี้ไม่ถูกตัวแปรละครับ ไม่งั้นโปรแกรมจะทำงานผิดพลาดครับ

การจองหน่วยความจำ

. . . . . . . .การใช้งานพอยน์เตอร์ เป็นแค่ตำแหน่งเฉยๆ แต่ไม่มีพื้นที่ใช้งาน เราต้องจองพื้นที่ใช้งาน สำหรับเก็บข้อมูล และเราก็ต้องยกเลิกเมื่อไม่ใช้งานแล้ว ดังตัวอย่างต่อไปนี้
#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <malloc.h>

int main( )

char *data = (char *)malloc( 20 ); //<----- จองพื้นที่ใช้งาน

strcpy( data, "Sawasdee" );

printf( "%s\n", data );

free( data ); //<----- ยกเลิกพื้นที่ที่จอง

return 0;

}

Sawasdee
. . . . . . . .จากข้างบนเราเรียก function malloc สำหรับจองพื้นที่ใช้งาน อันเนื่องมาจากว่า ตัวแปรพอนต์เตอร์มีขนาดแค่ 4 ตัวอักษร มีหน้าที ชี้ไปยังตำแหน่งที่ต้องการเท่านั้นเอง เราจึงต้องจองพื้นที่ใช้งาน มาก่อนแล้วให้ตัวแปรพอนต์ชี้ไป แล้วถึงจะใช้งานได้ และหลังจากใช้งานเสร็จเราก็ยกเลิก หน่วยความจำนั้นทันทีโดยใช้ function free ไม่น่ายากอะไรดูข้างบนอีกครั้งนะครับ และถ้าเป็นการเขียนแบบ C++ เราสามารถเขียนได้แบบนี้ ดูตัวอย่าง
#include <stdio.h>

#include <conio.h>

#include <string.h>

int main( )

{

char *data = new char[ 20 ];

strcpy( data, "Sawasdee" );

printf( "%s\n", data );

delete data;

return 0;

}

Sawasdee
. . . . . . . .จากข้างบนเราเรียก function new สำหรับจองพื้นที่ใช้งาน และยกเลิกด้วย function delete แต่การทำงานเหมือนกันครับ ไม่ยากเลยใช่ไหม ลองดูอีกแบบนะครับ
#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <malloc.h>

int main( )

{

intr *data = (int *)malloc( 3 );

data[0] = 10;

data[1] = 20;

data[2] = 30;

printf( "%i %i %i\n", data[0], data[1], data[2] ); //<--- ใช้เหมือน array

free( data );

return 0;

}

10 20 30
. . . . . . . .จากข้างบนเราเมื่อเราจองพื้นที่ทำงานแล้ว เราสามารถอ้างได้เหมือน array เลย ดูดี ดีสิ สำคัญจองไปไว้เท่าไรอย่าใช้เกินนะครับ จุดเริ่มต้นใช้งานให้นับจาก 0 นะครับ อย่าลืมๆ ต่อไปเป็นการจองพื้นที่ให้กับตัวแปรโครงสร้าง ก็ไม่มีอะไรมาก ลองดู
#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <malloc.h>

typedef struct TRecord

{

char data[80];

};

int main( )

{

struct TRecord *rec1 = (struct TRecord *)malloc( sizeof( TRecord ); //<-- จองพื้นที่ใช้งาน

strcpy( rec1 -> data, "Sawasdee" ); //<--- ให้ค่าฟิลด์

printf( "%s", rec1 -> data );

free( rec1 ); //<--- ยกเลิกพิ้นที่ใช้งาน

return 0;

}

Sawasdee
. . . . . . . .วิธีใช้ function malloc ให้ใส่จำนวนพื้นที่ที่ต้องการ ขนาดเป็น 1 ตัวอักษร แต่เราใช้ function sizeof เข้ามาช่วยคำนวณขนาดของ TRecord หลังจากนั้นให้ค่าตำแหน่งที่จองได้แก่ พอยน์เตอร์ rec1 และการเข้าถึงฟิลด์ในโครงสร้างต้องใช้เครื่องหมาย -> ไม่ใช่จุดไข่ปลานะครับ อย่าลืมๆ หลังจากนั้นยกเลิกด้วย function free มาดูตัวอย่างที่เขียนด้วย C++ กันบ้าง
#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <malloc.h>

struct TRecord

{

char data[80];

};

int main( )

{

TRecord *rec1 = new TRecord;

strcpy( rec1 -> data, "Sawasdee" ); //<--- ให้ค่าฟิลด์

printf( "%s", rec1 -> data );

delete rec1;

return 0;

}

Sawasdee
. . . . . . . .นี่คือข้อดีของ C++ จะเห็นว่า จะสั้นกว่า C ธรรมดามาก แต่ทำงานเหมือนกัน ลองเปรียบเทียบดูนะครับ

วันนี้ได้อะไรหว่า ???

int *pointer1; //<----- วิธีกำหนดตัวแปร พอยน์เตอร์

pointer1 = &value1; //<--- ให้ pointer ชี้ไปยังตำแหน่งของ value1 ที่เก็บค่า 10

intr *data = (int *)malloc( 3 );

data[0] = 10;

data[1] = 20;

data[2] = 30;

printf( "%i %i %i\n", data[0], data[1], data[2] ); //<--- ใช้เหมือน array

char *data = (char *)malloc( 20 ); //<----- จองพื้นที่ใช้งาน

free( data ); //<-- ยกเลิกพื้นที่ใช้งาน

char *data = new char[ 20 ];

delete data; //<-- ยกเลิกพื้นที่ใช้งาน

struct TRecord *rec1 = (struct TRecord *)malloc( sizeof( TRecord ); //<-- จองพื้นที่ใช้งาน

strcpy( rec1 -> data, "Sawasdee" ); //<--- ให้ค่าฟิลด์

printf( "%s", rec1 -> data );

free( rec1 ); //<--- ยกเลิกพิ้นที่ใช้งาน

TRecord *rec1 = new TRecord;

delete rec1;

. . . . . . . .วันนี้ออกจะสั้นเพราะเป็นเนื้อหาที่ไม่ซับซ้อนมากนัก แต่ควรจะลองเขียนบ่อยๆ เพราะไม่ยากเกินไปสำหรับเรา แต่เป็นพื้นฐานที่ควรรู้สำหรับโปรแกรมเมอร์ หมั่นเขียนบ่อยๆ ขยัน อดทน เพราะต่อไปเป็นการเขียนกราฟฟิกแล้วครับ :D