x 0 400 *ip = 0; y 1 402 101 ip 400 500 iq 502
x 0 400 y = 5; y 5 402 102 ip 400 500 iq 502
x 0 400 ip = &y; y 5 402 103 ip 402 500 iq 502
x 0 400 *ip = 3; y 3 402 104 ip 402 500 iq 502
x 0 400 iq = ip; y 3 402 105 ip 402 500 iq 402 502
6.4 แ รกิ เม ฟั ก (Pointer and Function Arguments) เนือ่ งจากภาษาซีมีการสง่ อากวิ เมนตใ์ ห้กับฟังกช์ นั แบบ By Value และฟงั กช์ นั สามารถคืนค่า (return) ค่าได้ เพยี งหนึ่งคา่ หากต้องการให้ฟงั ก์ชนั มีการ เปล่ยี นแปลงคา่ และคืนคา่ กลับมายังฟังก์ชนั ทเี่ รียกใช้ มากกวา่ หนึ่งคา่ จะต้องนาพอยน์เตอร์เขา้ มาชว่ ย 106
ตวั อย่างเช่น หากต้องการเขียนฟงั ก์ชนั เพ่ือสลับค่า ของตัวแปร 2 ตวั ผลลัพธ์ที่ต้องการได้จากฟังก์ชนั นจ้ี ะมี 2 คา่ ของตวั แปรทท่ี าการสลบั ค่า หากอาร์กิวเมนต์เป็นตัว แปรธรรมดาจะไม่สามารถแกป้ ญั หานีไ้ ด้ จงึ ตอ้ งใชพ้ อยน์ เตอรเ์ ข้ามาช่วย โดยการสง่ คา่ แอดเดรสของตวั แปรทัง้ 2 ใหก้ ับฟังกช์ นั ที่จะสลับคา่ ของตัวแปรทง้ั 2 ผ่านทางตวั แปร พอยนเ์ ตอร์ทเี่ ปน็ อารก์ ิวเมนตข์ องฟงั ก์ชัน 107
ตวั อย่าง 6.1 โปรแกรมตวั อย่างการสลับค่าตวั แปร 2 ตวั โดยผา่ นฟังกช์ นั จะแสดงการสง่ อารก์ ิวเมนต์ในเป็นพอยนเ์ ตอร์ #include <stdio.h> void swap (int *, int *); 108
ตัวอย่าง 6.1 (ต่อ) void main ( ) { int x = 5, y = 10; printf(“Before swap : x = %d”, x, “, y = %d\\n”, y); swap ( &x, &y); printf(“After swap : x = %d”, x, “, y = %d\\n”, y); } 109
ตัวอยา่ ง 6.1 (ต่อ) void swap (int *px, int *py) { int temp; temp = *px; *px = *py; *py = temp; } 110
อารก์ วิ เมนท์ท่ีเปน็ ประเภทพอยน์เตอรจ์ ะช่วย ใหฟ้ งั กช์ ันสามารถเปลี่ยนคา่ ใหก้ ับตวั แปรท่สี ง่ เข้า มาได้ เน่ืองจากอารก์ ิวเมนท์นัน้ จะเก็บแอดเดรส ของตัวแปรที่สง่ เข้ามา เม่ือมกี ารเปลยี่ นแปลงคา่ ของอารก์ วิ เมนทผ์ า่ น Dereferencing Operator ( * ) ค่าของตวั แปรทสี่ ง่ เข้ามาจะถูกเปลย่ี นค่าพร้อมกนั ในทันที 111
in main ( ) x y in swap ( ) px py รป ่ 6.4 แ ม มพ ธ ก ร รกิ เม แ พ เ รก ฟั ก 112
6.5 ก รเร (Pointer and Arrays) อารเ์ รย์เปน็ ประเภทข้อมูลท่ีเก็บชุดของข้อมลู ประเภทเดียวกนั มกั ใช้กบั การทางานทีต่ อ้ งทางาน กับตัวแปรชนดิ เดียวกนั หลายตวั ที่มกี ารทางาน เหมือนกัน เช่น คะแนนของนกั ศกึ ษาภายในห้อง 20 คน เป็นต้น อาร์เรยใ์ นภาษาซีจะนาหลกั การของ พอยนเ์ ตอร์เข้ามาใช้ การทางานใด ๆ ของอาร์เรย์ สามารถใช้พอยนเ์ ตอรเ์ ข้ามาแทนที่ 113
การประกาศอารเ์ รย์ int table[10]; เป็นการกาหนดอาร์เรยช์ อ่ื table เปน็ อาร์เรย์ประเภท int ทีม่ ีสมาชิกทั้งหมด 10 ตวั ต้งั แต่ table[0], table[1], table[2], ... , table[9] สมาชิกภายในอารเ์ รย์จะเร่ิมท่ี 0 เสมอ และสมาชิกตวั สุดทา้ ยจะอย่ทู ตี่ าแหนง่ ของขนาด ทีป่ ระกาศไว้ลบด้วย 1 114
table table[9] table[0] table[1] table[2] รูปที่ 6.5 แสดงภาพจาลองของอารเ์ รยข์ นาด สมาชกิ 10 ตัว 115
การอา้ งถึงสมาชิกในอารเ์ รย์ จะใช้ระบบดชั นีโดยผ่านเคร่อื งหมาย [ ] เชน่ อา้ งถึงสมาชกิ ตวั ที่ 3 ของอารเ์ รยด์ ว้ ย table[2] เปน็ ตน้ การใชง้ านสมาชิกของอารเ์ รย์สามารถใชง้ านได้เหมอื น ตวั แปรพนื้ ฐานท่วั ไป 116
ตวั อย่าง sumThird = table[0] + table[1] + table[2]; table[0] = 5; if ( a[0] > a[9] ) printf (“First is greater than last\\n” ); 117
เราสามารถอ้างถงึ สมาชิกทกุ ตวั ภายใน อารเ์ รยอ์ ยา่ งอสิ ระ ภายในขอบเขตของขนาดที่ ไดป้ ระกาศอารเ์ รย์ไว้ แต่การใชอ้ ารเ์ รย์มกั จะ เป็นการเขา้ ถึงสมาชิกในลักษณะทวั่ ไปโดยใช้ ตัวแปรประเภท int มาช่วย 118
ตวั อย่าง สมมติให้ i, j, k เป็นตัวแปรประเภท int for (int k = 0; k < 9; k++) printf (“Value at %d = %d\\n”, k+1, table[k]); table[i + j] = 0; table[7 – table[j]] = j; 119
ส่ิงที่ตอ้ งระวงั ในภาษาซีจะไมม่ กี ารกาหนดให้ตรวจสอบ ขอบเขตของอารเ์ รย์ โปรแกรมเมอรจ์ ะตอ้ งพยายาม เขยี นโปรแกรมทีเ่ กยี่ วข้องกบั สมาชิกของอารเ์ รย์ ภายในขอบเขตท่ีประกาศอารเ์ รยไ์ ว้ หากมกี ารอา้ งอิง ถงึ สมาชิกอารเ์ รย์นอกขอบเขตที่ได้ระบุไว้ เชน่ table[12] สิง่ ทไ่ี ดค้ ือการไปอ่านข้อมลู ในพน้ื ที่ของ หนว่ ยความจาทอี่ าจจะเกบ็ คา่ ของตัวแปรตัวอนื่ หรือ คา่ อ่ืนใดที่ไมอ่ าจคาดเดาได้ 120
ตัวอย่าง 6.2 ใหอ้ า่ นค่าของจานวนเต็ม 5 จานวนจาก คีย์บอร์ด และแสดงผลในลาดบั ทก่ี ลับกัน # include <stdio.h> #define SIZE 5 main ( ) { int k; int table[SIZE]; for (k = 0; k < SIZE; k++) scanf (“%d”, &table[k]); for (k = SIZE-1; k >= 0; k--) printf (“%d\\n”, table[k]); } 121
สมาชกิ ของอาร์เรยอ์ าจเปน็ ประเภทขอ้ มูล พื้นฐานใด ๆ กไ็ ด้ หรอื อาจเป็นขอ้ มลู ประเภท Enumeration เชน่ #define TSIZE 10 #define NAMESIZE 20 #define ADDRSIZE 30 enum month { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } 122
typedef enum month Month; int age[TSIZE]; float size[TSIZE+1]; Month date[8]; char name[NAMESIZE], address[ADDRSIZE]; 123
6.6 ก รใ ก รเร การทางานใด ๆ ของอารเ์ รย์สามารถใช้พอยนเ์ ตอร์เข้ามา ช่วย ซ่งึ จะทาใหม้ คี วามเรว็ ในการทางานสงู ขน้ึ สมมติว่า มีอารเ์ รย์ a และพอยนเ์ ตอร์ pa ดงั น้ี int a[10]; int *pa; กาหนดใหพ้ อยนเ์ ตอร์ pa ชีไ้ ปยงั อารเ์ รย์ a ด้วยคาส่งั pa = &a[0]; /* หรอื ใช้คาสั่ง pa = a; */ pa จะเกบ็ คา่ แอดเดรสเริ่มต้นของอารเ์ รย์ a 124
pa a[9] a a[0] a[1] a[2] รูปท่ี 6.6 แสดงตัวชชี้ ้ีไปยังแอดเดรสเร่ิมตน้ ของอาร์เรย์ 125
การนาไปใช้งานจะสามารถอา่ นค่าอาร์เรย์ ผ่านพอยน์เตอร์ได้ดังนี้ x = *pa; จะเปน็ การกาหนดคา่ ให้ x มีค่าเท่ากบั a[0] การ เล่อื นไปอ่านคา่ สมาชกิ ตาแหน่งต่าง ๆ ของอารเ์ รย์ ผา่ นทางพอยนเ์ ตอรส์ ามารถทาได้โดยการเพิ่มคา่ พอยนเ์ ตอร์ขน้ึ 1 เพ่อื เลื่อนไปยังตาแหน่งถัดไป หรอื เพ่ิมค่าข้นึ N เพ่อื เลือ่ นไป N ตาแหน่ง หรอื อาจจะลดคา่ เพ่ือเลอ่ื นตาแหนง่ ลง 126
กรณที ี่ pa ชี้อยทู่ ี่ a[0] คาสัง่ pa+1; จะเป็นการอ้างถงึ แอดเดรสของ a[1] หากเป็น pa+i เปน็ การอ้างถึงแอดเดรส a[i] หาก ตอ้ งการอ้างถงึ ข้อมูลภายในของสมาชกิ ของ อาร์เรย์ตาแหนง่ ท่ี a[i] จะใช้ *(pa+i) 127
pa pa+ pa+ a[9] 12 a a[0] a[1] a[2] รูปท่ี 6.7 แสดงการอ้างถงึ ตาแหนง่ ในอารเ์ รยผ์ า่ นตวั ช้ี 128
การสัง่ ใหบ้ วก 1 หรือบวก i หรอื ลบ i เปน็ เหมอื น การเล่ือนไปยังสมาชกิ ของอารเ์ รยต์ าแหน่งทตี่ ้องการ เนอ่ื งจากประเภทของข้อมลู แตล่ ะประเภทของอาร์เรย์ เช่น int, float, double และอนื่ ๆ มขี นาดของข้อมูลทต่ี า่ งกนั ทา ให้ขนาดของสมาชิกภายในอาร์เรยแ์ ต่ละประเภทมีขนาด แตกตา่ งกันด้วย การสงั่ ให้บวกหรอื ลบด้วยจานวนท่ตี อ้ งการ น้ันจะมีกลไกท่ที าหน้าทคี่ านวณตาแหน่งท่ีตอ้ งการให้ สอดคล้อง กับขอ้ มลู แต่ละประเภทโดยอตั โนมตั ิ 129
นอกจากนี้ยงั สามารถใชพ้ อยน์เตอร์แทนอาร์เรย์ การอ้างโดยใช้ a[i] สามารถใช้ *(a+i) เนอื่ งจากทกุ คร้งั ที่อา้ งถึง a[i] ภาษาซีจะทาหน้าท่ีแปลงเป็น *(a+i) เพราะฉะน้นั การเขียนในรูปแบบใดกใ็ ห้ผลลพั ธใ์ นการ ทางานเช่นเดียวกัน และการอ้างถงึ แอดเดรส เช่น &a[i] จะมีผลเท่ากบั การใช้ a+i 130
ในลกั ษณะเดยี วกนั การใช้งานพอยน์เตอรก์ ส็ ามารถใช้ คาส่ังในลกั ษณะอาร์เรย์ก็ได้ เชน่ การอ้างถึง *(pa+i) สามารถเขียนดว้ ย pa[i] กไ็ ด้ผลเชน่ เดียวกัน สงิ่ ท่แี ตกตา่ งกันของอารเ์ รย์และพอยนเ์ ตอร์ คอื พอยน์ เตอรเ์ ป็นตวั แปร แตอ่ าร์เรย์ไม่ใช่ตวั แปร สมมติให้ a เปน็ อารเ์ รยแ์ ละ pa เป็นพอยน์เตอร์ การอ้างถึง pa = a หรือ pa++ จะสามารถคอมไพล์ได้ แตจ่ ะไมส่ ามารถใช้คาสั่ง a = pa หรอื a++ ได้ 131
เม่ือมกี ารสง่ ช่ือของอาร์เรยใ์ ห้แกฟ่ งั กช์ ัน จะ เป็นการส่งตาแหนง่ แอดเดรสของสมาชิกตัวแรก ของอารเ์ รย์ใหแ้ กฟ่ ังกช์ นั ดังนัน้ พารามเิ ตอร์ใน ฟังกช์ ันน้ันจะเป็นตัวแปรประเภทพอยน์เตอร์ 132
ตัวอยา่ ง 6.3 ฟงั ก์ชันทร่ี ับพารามเิ ตอร์เป็นพอยน์เตอร์ โดยอาร์กวิ เมนท์ท่สี ่งมาเป็นอารเ์ รย์ int strlen (char *s) { int n; for ( n = 0; *s != ‘\\0’; s++ ) n++; return n; } 133
จะเหน็ วา่ s เปน็ พอยน์เตอร์ ในฟงั ก์ชนั จะมกี ารตรวจสอบ ข้อมูลวา่ มคี ่าเท่ากบั ‘\\0’ หรือไม่ และมีการเลอื่ นตาแหน่งที ละ 1 ค่า (นบั ว่าขอ้ มลู มีความยาวเพม่ิ ข้ึนทลี ะ1) โดยใช้ s++ การเรียกใช้ฟังกช์ นั strlen สามารถทาไดห้ ลายลกั ษณะ strlen (“hello world”); /* string constant */ strlen (array); /* char array[10] */ strlen (ptr); /* char *ptr; */ 134
นอกจากน้ียังอาจจะประกาศพารามิเตอร์ภายใน ฟังก์ชนั strlen ได้ใน 2 ลกั ษณะ คอื char *s แบบใน ตัวอยา่ ง หรอื อาจจะใช้ char s[ ] กไ็ ด้ โดยท่ัวไปจะ ใช้ในลักษณะแรก เพราะช่วยในร้ไู ดท้ ันทีวา่ s เปน็ ตัว แปรพอยน์เตอร์ และยงั สามารถส่งสว่ นใดส่วนของ อารเ์ รย์ให้แก่ฟังกช์ ันก็ได้ โดยไม่จาเปน็ ตอ้ งส่งสมาชิก ตวั แรกกไ็ ดเ้ ชน่ กัน 135
ตวั อยา่ ง f (&a[2]) หรือ f (a+2) เปน็ การส่งแอดเดรสของสมาชิก a[2] ใหก้ บั ฟงั ก์ชนั f การประกาศฟังกช์ นั f สามารถทาไดโ้ ดย การประกาศ f (int arr[ ]) { ......... } หรอื f (int *arr) { ............ } 136
6.7 ก ร ก แ เ ร ให้ p เปน็ พอยนเ์ ตอร์ชไี้ ปยงั อาร์เรยใ์ ด ๆ คาสั่ง p++ เปน็ การเลื่อน p ไปยงั สมาชิกถัดไป และคาส่งั p += i เปน็ การเลื่อนพอยน์เตอรไ์ ป i ตาแหนง่ จากตาแหน่ง ปัจจุบนั นอกจากนี้ยังสามารถใช้เครือ่ งหมาย ความสัมพันธ์ (Relational Operator) เช่น ==, !=, <, >= และอนื่ ๆ ทางานร่วมกับพอยน์เตอร์ได้ สมมติให้ p และ q ชีไ้ ปยังสมาชิกของอารเ์ รยเ์ ดียวกัน 137
p<q จะเป็นจริงเม่อื p ชไ้ี ปท่ีสมาชิกทอ่ี ย่กู อ่ นหน้าสมาชกิ ท่ี q ชอ้ี ยู่ การเปรียบเทียบในลักษณะจะใชไ้ ด้ ต่อเม่ือ p และ q ช้ไี ปทอ่ี าร์เรย์เดียวกันเท่านั้น นอกจากน้ียงั สามารถใช้การลบหรอื การบวก กับพอยน์เตอร์ไดเ้ ชน่ เดียวกนั แต่สง่ิ ทีค่ วรระวังคือ การทาเชน่ นน้ั จะต้องอยใู่ นขอบเขตขนาดของ อารเ์ รย์เท่านนั้ 138
ตวั อย่าง 6.3 ฟังกช์ นั strlen( ) ปรับปรุงให้กระชบั ข้ึน int strlen (char *s) { char *p = s; while (*p != ‘\\0’) p++; return p-s; } 139
เนอ่ื งจาก s ช้อี ยู่ท่ตี าแหน่งเร่ิมต้น โดยมี p ชไ้ี ปที่ s เช่นเดยี วกนั แตจ่ ะมีการเลอื่ น p ไปทลี ะหนงึ่ ตาแหนง่ จนกว่าคา่ ท่ตี าแหน่งท่ี p ชอี้ ยจู่ ะเท่ากับ ‘\\0’ เม่อื นา p คา่ สุดทา้ ยมาลบกบั s ที่ตาแหนง่ เริม่ ต้นกจ็ ะไดค้ วามยาวของขอ้ มลู ที่ ส่งเข้ามา 140
6.8 ก รแ ฟั ก (Character Pointer and Function) การทางานกับขอ้ ความหรือทเี่ รยี กว่า สตรงิ (String) เป็นการใช้ขอ้ มูลตวั อักษรหลาย ๆ ตัว หรืออาร์เรย์ของขอ้ มลู ประเภท char หรืออาจจะ ใชพ้ อยนเ์ ตอร์ชี้ไปยังขอ้ มูลประเภท char การ ทางานกบั ค่าคงทส่ี ตรงิ (String Constant) สามารถ เขียนภายในเครอ่ื ง “ ” 141
ตวั อย่าง “I am a string” เมือ่ มีการใชค้ ่าคงที่สตริงจะมกี ารพ้ืนท่ีในหน่วยความจา เทา่ กับความยาวของค่าคงทสี่ ตรงิ บวกด้วย 1 เน่ืองจาก ลักษณะการเกบ็ ขอ้ มลู ประเภทขอ้ ความใน หน่วยความจาจะมกี ารปะตัวอักษร null หรือ ‘\\0’ ต่อทา้ ย เสมอเพอ่ื ให้รู้ว่าเป็นจดุ สนิ้ สุดของข้อมูล การจองพ้นื ท่ี ดังกลา่ วจะเหมือนการจองพน้ื ที่ของขอ้ มูลประเภท อารเ์ รย์ เป็นอารเ์ รย์ของ char 142
I a m a s t r i n g \\0 รปู ที่ 6.8 แสดงแบบจาลองการเกบ็ ขอ้ มูลประเภท สตรงิ ในหนว่ ยความจา 143
คา่ คงทสี่ ตริงที่พบเหน็ ไดเ้ สมอไดแ้ ก่ขอ้ ความ ทใ่ี ชใ้ นฟงั ก์ชนั printf ( ) เชน่ printf ( “Hello, world\\n” ); ฟังก์ชัน printf ( ) จะรบั พารามเิ ตอร์เปน็ พอยนเ์ ตอรช์ ี้ไปยงั แอดเดรสของขอ้ มลู ท่ีตาแหน่ง เร่ิมต้นของอารเ์ รย์ และนาข้อความนัน้ แสดงออก ทางอุปกรณแ์ สดงขอ้ มูลมาตรฐาน 144
ในการเขยี นโปรแกรมจะสามารถใช้พอยน์ เตอรช์ ี้ไปคา่ คงทส่ี ตริงใด ๆ กไ็ ด้ เช่น char *pmessage = “Hello, world”; pmessage จะเป็นพอยน์เตอร์ประเภท char ชีไ้ ปทีอ่ ารเ์ รยข์ องตวั อักษร จะแตกตา่ งจากการใช้ อารเ์ รย์ท่ัวไปเช่น char amessage[ ] = “Hello, world”; 145
ลักษณะของอาร์เรยเ์ ช่น amessage จะมี การจองพ้ืนท่ีใชก้ บั อาร์เรยข์ นาด 13 ตวั อกั ษร รวมทั้ง null สว่ นลกั ษณะของพอยน์เตอรท์ ่ชี ี้ไปยงั คา่ คงทีส่ ตรงิ จะมกี ารจองพนื้ ท่ใี หก้ บั ค่าคงที่สตริง ขนาด 13 ตวั อกั ษรเช่นเดียวกนั แต่จะมกี ารจอง พ้ืนทีใ่ หก้ บั พอยนเ์ ตอร์และทาการชี้พอยน์เตอรน์ ้ัน ไปยงั พ้ืนทข่ี องค่าคงทส่ี ตรงิ ทจี่ องเอาไว้ 146
pmessage w o r l d \\0 He l l o , amessage H e l l o , w o r l d \\0 รูปที่ 6.9 การจองพืน้ ทใ่ี ห้กับอารเ์ รย์และตวั ชชี้ ีไ้ ปยังคา่ คงท่ีสตรงิ 147
ตัวอยา่ ง 6.5 ฟังกช์ นั strcpy ( ) ทาหนา้ ทสี่ าเนา ขอ้ ความจากตวั แปรหนง่ึ ไปยังอกี ตวั แปรหนึ่งเขยี นในลกั ษณะอารเ์ รย์ void strcpy ( char *s, char *t ) { int i=0; while ( ( s[i] = t[i] ) != ‘\\0’ ) i++; } 148
ตวั อย่าง 6.6 ฟังก์ชนั strcpy ( ) เขยี นในลกั ษณะ พอยนเ์ ตอร์ void strcpy ( char *s, char *t ) { while ( ( *s = *t ) != ‘\\0’ ) { s++; t++; } } 149
ตวั อยา่ ง 6.7 ฟังกช์ นั strcpy ( ) เขยี นในลกั ษณะ พอยน์เตอรแ์ บบส้นั void strcpy ( char *s, char *t ) { while ( ( *s++ = *t++ ) != ‘\\0’ ) ; } 150
Search
Read the Text Version
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177