structure & union (Basic Programming)
structure และ union ดูเหมือนจะเป็นเรื่องใกล้ตัวของโปรแกรมเมอร์ทั่วไป แต่จะมีสักกี่คนที่จะใช้สิ่งนี้ในการเขียนโปรแกรมของเขา การไม่ใช้หมายถึง เขาไม่เห็นประโยชน์ของมัน ใช้ไม่เป็น หรืออะไรกันแน่ อันนี้ตอบยาก เพราะต่างคนย่อมต่างกัน
ส่วนตัวผมเขียนโปรแกรมหลากหลายรูปแบบ ไม่ว่าจะเป็นบนคอมพิวเตอร์ หรือบนไมโครคอนโทรลเลอร์ แนวการเขียนก็จะไม่ค่อยเหมือนชาวบ้าน เท่าไร่ แต่ก็ยังคงความเป็นมาตรฐานของการเขียนโปรแกรมเอาไว้ (แน่ล่ะสิ ไม่คงมาตรฐานไว้ก็คอมไพล์ไม่ผ่านสินะ)
บทความนี้จะแนะนำการใช้ตัวแปรแบบ structure ไปพร้อมๆ กับการใช้ union สองตัวนี้ไม่ค่อยมีประโยชน์กับการเขียนโปรแกรมแบบขอไปที หรือใช้เสร็จๆไป เพราะดูเหมือนเป็นเรื่องเสีจยเวลาโดยใช่เหตุ (สำหรับโปรแกรมเล็กๆ) แต่จะมี ประโยชน์อย่างมากในการเขียนโปรแกรมอย่างเป็นระบบ การวางโครงสร้างของ โปรแกรม การประหยัดหน่วยความจำ การเพิ่มความเร็วการประมวลผล รวมไปถึง ความง่ายของการเขียนโปรแกรม (ใช้โครงสร้างที่คนอื่นวางไว้ให้แล้ว)
เพื่อให้เห็นภาพกันแบบชัด ผมจะขอยกตัวอย่างตัวแปรแบบโครงสร้างขนาด 8-bit มีรูปร่างหน้าตาแบบนี้ อย่างที่ทราบกัน ตัวแปรแบบ 8-bit ก็คือตัวแปรขนาด 1 byte มาทบทวนกันหน่อย 1 byte = 8 bits 4 bits = 1 nibble 2 nibbles = 1 byte = 8bits 4 bits lower = low-nibble 4 bits higher = high-nibble
เขียนให้ งง เข้าไว้ แต่ความสัมพันธ์และนิยามมันเป็นแบบนั้นจริงๆ และด้วย ความสัมพันดังกล่าว ชัดเจนว่า คำว่า "byte" มันมีทั้ง "nibble" และ "bits" ประกอบอยู่เป็นอันหนึ่งอันเดียวกัน ผมก็สามารถจะออกแบบโครงสร้างของ ตัวแปรตัวนี้ได้ ส่วนคำว่า "union" ก็หมายถึงอะไรสองอย่างขึ้นไปมาไว้ในกล่อง ใบเดียวกันนั่นเอง ในที่นี้คือนำ nibble กับ Bits ไปไว้ในกล่อง Byte นั่นเอง สมมุตติว่าผมอ้างถึงบิตที่ 4 (BIT4) ของ Byte นั่นคือการอ้างถึง บิทต่ำสุด ของ high-nibble (Hi) นั่นเอง อย่าเพิ่ง งง ครับ เดี๋ยวค่อยมาดูตัวอย่างกัน จากโครงสร้างด้านบน ชื่อของโครงสร้างหรือ structure คือ VAR8 นี่คือกล่องใบใหญ่สุด ในกล่องใบนี้มีกล่อง อีกใบชื่อ Data ในกล่อง Data ยังมีกล่องใบเล็กๆ อีก 3 ใบคือ Byte ใน Byte มี Nibble และ Bits มองลึกลงไปในแต่ละกล่อง จะเห็นว่ากล่อง Nibble มีอีกสองกล่อง คือ Lo และ Hi และที่กล่อง Bits มีของชิ้นเล็กๆ อีก 8 ชิ้น คือ BIT0 ถึง BIT7
แต่อย่าลืมนะครับว่ากล่อง Byte, Nibble และ Bits เกิดจากการ union การกระทำอะไร บางอย่างกับส่วนใดส่วนหนึ่งจะส่งผลโดยตรงกับสิ่งที่อยู่ในกล่องใบอื่นด้วย มาดูตัวอย่างกัน
บรรทัดที่ 1 คือการประกาศขอใช้ตัวแปรชนิด VAR8 ชื่อ MyVar บรรทัดที่ 2 ทำให้ Byte มีค่า 15 จะส่งผลให้ Lo มีค่าเม่ากับ 15 และ BIT0 ถึง BIT3 มีค่าเป็น 1 ทุกบิต (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0x0F) บรรทัดที่ 3 ทำให้ BIT7 มีค่าเป็น 1 จะส่งผลให้ บิตที่ 8 ของ Byte เป็น 1 และ บิตที่ 4 ของ Hi มีค่าเป็น 1 ด้วย (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0x8F) บรรทัดที่ 4 ทำให้ Hi มีค่า 15 จะส่งผลให้ BIT4 ถึง BIT7 เป็น 1 และบิตที่ 4-7 ของ Byte เป็น 1 ด้วย (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0xFF) บรรทัดที่ 5 ทำให้ Lo มีค่า เป็น 0 จะส่งผลให้ BIT4 ถึง BIT7 เป็น 0 และบิตที่ 4-7 ของ Byte เป็น 0 ด้วย (ตอนนี้ค่าสะสมของ Byte มีค่าเป็น 0xF0) เห็นหรือยังครับว่า การเปลี่ยนข้อมูลส่วนใดส่วนหนึ่ง จะส่งผลกับข้อมูลในส่วนอื่นๆ ด้วย การทำความเข้าใจอาจจะลำบากหากเรื่องนี้ไม่เคยผ่านหูผ่านตา ควรอ่านไปเขียนไป เพื่อเพิ่มความเข้าใจสิ่งที่ผมอธิบาย
แล้วจะมีประโยชน์อะไร? ทำไมไม่ประกาศเป็น char หรือ unsigned char ไปเลยล่ะ 8 bits เหมือนกัน ใช้งานง่ายกว่าด้วย
นั่นน่ะสิ.... เพื่อให้เข้าใจมากขึ้น ขอยกตัวอย่างในโลกของไมโครคอนโทรลเลอร์ก็แล้วกัน ในโลกของไมโครคอนโทรลเลอร์ คือการเขียน/อ่านค่าต่างๆ กับรีจิสเตอร์ ซึ่งรีจิสเตอร์ ยกตัวอย่างเช่น รีจิสเตอร์ที่ทำหน้าที่ควบคุมการทำงานของ Timer/Counter ในไมโครคอน โทรลเลอร์แบบ 8-bit รีจิสเตอร์ก็จะมีขนาด 8-bit หรือ 1 byte ในแต่ละ bit ถูกใช้ในการ กำหนดการทำงานรูปแบบต่างๆ ยกตัวอย่างเช่น บิค 0-3 ใช้กำหนดการทำงานของ Pre-scaler บิตที่ 7 เปิดปิดการทำงานของ Timer/Counter การเขียนโปรแกรมก็เพียงแค่อ้างโดยการใช้ REGISTER.DATA.PRESCALER หรือ REGISTER.DATA.BIT7 เพื่ออ้างถึง Pre-scaler และ เปิดปิดการทำงานของ Timer/Counter โดยไม่ต้องทราบเลยว่ามันอยู่บิตไหน และไม่ต้องกลัว ว่าจะเป็นเปลี่ยนข้อมูลในส่วนที่ไม่ได้ตั้งใจ ที่สำคัญช่วยให้เขียนโปรแกรมได้โดยไม่ต้องเปิด datasheet เพียงแค่จำชื่อของสิ่งที่สนใจก็เพียงพอ
typedef struct{ union{ BYTE Byte; struct{ BYTE Lo : 4; BYTE Hi : 4; }Nibble; struct{ BYTE BIT0 : 1; BYTE BIT1 : 1; BYTE BIT2 : 1; BYTE BIT3 : 1; BYTE BIT4 : 1; BYTE BIT5 : 1; BYTE BIT6 : 1; BYTE BIT7 : 1; }Bits; }Data; }VAR8;
VAR8 MyVar;
void main(void){ MyVar.Data.Byte = 15; MyVar.Data.Bits.BIT7 = 1; MyVar.Data.Nibble.Hi = 15; MyVar.Data.Nibble.Lo = 0; }
By: Santi @ //www.shadowwares.com/forum
Create Date : 21 มีนาคม 2554 |
|
0 comments |
Last Update : 21 มีนาคม 2554 11:09:34 น. |
Counter : 1578 Pageviews. |
|
|
|