1. บทนำ
ลำดับความสำคัญของโอเปอเรเตอร์ในภาษา C มีความสำคัญอย่างมากต่อการทำความเข้าใจการทำงานของโปรแกรมอย่างถูกต้องและได้ผลลัพธ์ตามที่ต้องการ โดยเฉพาะอย่างยิ่ง หากเข้าใจลำดับการประเมินโอเปอเรเตอร์ผิด อาจเกิดผลลัพธ์ที่ไม่คาดคิดหรือเกิดบั๊กได้ บทความนี้จะอธิบายรายละเอียดเกี่ยวกับลำดับความสำคัญและกฎการเชื่อมของโอเปอเรเตอร์หลักในภาษา C พร้อมตัวอย่างเพื่อให้เข้าใจมากยิ่งขึ้น
2. ประเภทของโอเปอเรเตอร์และวิธีใช้งานเบื้องต้น
2.1 โอเปอเรเตอร์ทางคณิตศาสตร์
โอเปอเรเตอร์ทางคณิตศาสตร์เป็นโอเปอเรเตอร์พื้นฐานสำหรับการคำนวณตัวเลข ใช้งานบ่อยในโปรแกรม จึงควรเข้าใจพื้นฐานเหล่านี้ให้ดี
+(บวก): ใช้บวกตัวเลขสองตัว-(ลบ): ใช้ลบตัวเลขสองตัว*(คูณ): ใช้คูณตัวเลขสองตัว/(หาร): ใช้หารตัวเลขสองตัว (ถ้าเป็นจำนวนเต็ม ผลลัพธ์จะปัดเศษทิ้ง)%(หารเอาเศษ): ใช้หาค่าเศษที่เหลือจากการหาร
ตัวอย่าง:
int a = 10, b = 3;
int sum = a + b; // 13
int diff = a - b; // 7
int prod = a * b; // 30
int quot = a / b; // 3
int rem = a % b; // 12.2 โอเปอเรเตอร์เปรียบเทียบ
โอเปอเรเตอร์เปรียบเทียบจะใช้เปรียบเทียบค่าสองค่า แล้วคืนค่าจริง (1) หรือเท็จ (0) มักใช้ในเงื่อนไขและลูป
>(มากกว่า): เป็นจริงถ้าค่าซ้ายมากกว่าค่าขวา<(น้อยกว่า): เป็นจริงถ้าค่าซ้ายน้อยกว่าค่าขวา>=(มากกว่าหรือเท่ากับ): เป็นจริงถ้าค่าซ้ายมากกว่าหรือเท่ากับค่าขวา<=(น้อยกว่าหรือเท่ากับ): เป็นจริงถ้าค่าซ้ายน้อยกว่าหรือเท่ากับค่าขวา==(เท่ากัน): เป็นจริงถ้าค่าซ้ายและขวาเท่ากัน!=(ไม่เท่ากัน): เป็นจริงถ้าค่าซ้ายและขวาไม่เท่ากัน
int a = 5, b = 10;
if (a < b) {
printf("a น้อยกว่า b\n"); // จะแสดงผล
}

3. ลำดับความสำคัญและกฎการเชื่อมของโอเปอเรเตอร์
3.1 ลำดับความสำคัญของโอเปอเรเตอร์
ลำดับความสำคัญของโอเปอเรเตอร์จะเป็นตัวกำหนดว่าในนิพจน์ที่มีโอเปอเรเตอร์หลายตัว ตัวไหนจะถูกประเมินก่อน ตารางด้านล่างคือลำดับความสำคัญของโอเปอเรเตอร์บางส่วนในภาษา C เรียงจากลำดับสูงสุดไปต่ำสุด
| ลำดับ | โอเปอเรเตอร์ | คำอธิบาย |
|---|---|---|
| 1 | () [] -> . | เรียกฟังก์ชัน เข้าถึงอาร์เรย์ สมาชิกของพอยน์เตอร์ |
| 2 | ++ -- | เพิ่มค่า/ลดค่าทีละหนึ่ง (แบบ post-fix) |
| 3 | ++ -- | เพิ่มค่า/ลดค่าทีละหนึ่ง (แบบ prefix), โอเปอเรเตอร์เครื่องหมาย |
| 4 | * / % | คูณ, หาร, หาเศษ |
| 5 | + - | บวก, ลบ |
| 6 | << >> | บิตชิฟต์ |
| 7 | < <= > >= | โอเปอเรเตอร์เปรียบเทียบ |
| 8 | == != | เท่ากัน, ไม่เท่ากัน |
| 9 | & | บิต AND |
| 10 | ^ | บิต XOR |
| 11 | | | บิต OR |
| 12 | && | AND เชิงตรรกะ |
| 13 | || | OR เชิงตรรกะ |
| 14 | ? : | โอเปอเรเตอร์เงื่อนไข |
| 15 | = += -= | กำหนดค่า, กำหนดค่าแบบรวม |
| 16 | , | โอเปอเรเตอร์คอมม่า |
3.2 กฎการเชื่อมของโอเปอเรเตอร์
กฎการเชื่อม (Associativity) จะกำหนดว่าหากมีโอเปอเรเตอร์ลำดับเดียวกันหลายตัวในนิพจน์ จะประเมินจากด้านไหนก่อน โดยส่วนใหญ่เป็นเชื่อมซ้าย แต่บางโอเปอเรเตอร์ (เช่น โอเปอเรเตอร์กำหนดค่า และโอเปอเรเตอร์เงื่อนไข) เป็นเชื่อมขวา
- เชื่อมซ้าย: เช่น
*,+,-จะประเมินจากซ้ายไปขวา - เชื่อมขวา: เช่นโอเปอเรเตอร์กำหนดค่า และ
? :จะประเมินจากขวาไปซ้าย
int a = 5, b = 10, c = 15;
int result = a - b + c; // เชื่อมซ้าย (a - b) + c = 04. ข้อควรระวังเกี่ยวกับลำดับความสำคัญของโอเปอเรเตอร์บางประเภท
4.1 โอเปอเรเตอร์เชิงตรรกะ
โอเปอเรเตอร์ AND เชิงตรรกะ (&&) และ OR เชิงตรรกะ (||) มักใช้ในการเชื่อมเงื่อนไข โดย && จะมีลำดับความสำคัญสูงกว่า || ดังนั้นต้องระวังเวลาเขียนโค้ดดังนี้
int a = 1, b = 0, c = 1;
if (a && b || c) {
printf("Truen"); // จะแสดงผล
}ในตัวอย่างนี้ a && b จะถูกประเมินก่อน แล้วผลลัพธ์นั้นจะนำมา OR กับ c หากต้องการลำดับที่แน่นอนควรใช้วงเล็บเพื่อระบุ
if ((a && b) || c) {
// ชัดเจนกว่า
}4.2 โอเปอเรเตอร์บิต
โอเปอเรเตอร์บิต (&, |, ^) ใช้สำหรับการดำเนินการระดับบิต โดยปกติจะมีลำดับความสำคัญต่ำกว่าโอเปอเรเตอร์ทางคณิตศาสตร์และเปรียบเทียบ ดังนั้นหากนิพจน์ซับซ้อนควรระวัง
int x = 5; // 0101
int y = 3; // 0011
int result = x & y; // 0001 (AND บิต)
5. ตัวอย่างโปรแกรมจริง
ตัวอย่างโค้ดที่อาจทำให้เข้าใจผิดเกี่ยวกับลำดับความสำคัญของโอเปอเรเตอร์ โดยเฉพาะ || และ &&
#include <stdio.h>
int main() {
int a = 0, b = 1;
if (a == 0 || a == 1 && b == 0) {
printf("Truen"); // จะแสดงผล
}
return 0;
}ในตัวอย่างนี้ a == 1 && b == 0 จะถูกประเมินก่อน ซึ่งอาจไม่ได้ผลลัพธ์ตามที่ตั้งใจไว้ หากต้องการผลลัพธ์ที่ถูกต้องควรใช้วงเล็บระบุลำดับการประเมิน
if ((a == 0 || a == 1) && b == 0) {
printf("Truen");
}6. สรุป
ลำดับความสำคัญของโอเปอเรเตอร์ในภาษา C เป็นสิ่งสำคัญต่อการทำงานของโปรแกรมอย่างถูกต้อง เมื่อต้องจัดการกับนิพจน์ที่ซับซ้อนควรเข้าใจลำดับความสำคัญและกฎการเชื่อมให้ดี และใช้วงเล็บระบุลำดับเมื่อจำเป็น จะช่วยป้องกันบั๊กและได้โค้ดที่ถูกต้องและมีประสิทธิภาพมากขึ้น


