เล่นสนุกกับ C ตอน &((int*)-8)[3]
(lcamtuf.substack.com)- ซีรีส์ตอนที่สี่ว่าด้วยพื้นฐานภาษา C จัดเรียงหัวข้อการนิยามฟังก์ชัน, ลำดับความสำคัญของตัวดำเนินการ, goto, การนับและการบวก ด้วย โค้ดตัวอย่างแบบขี้เล่น
- ส่วนการนิยามฟังก์ชันแนะนำให้ใช้ การประกาศล่วงหน้า ให้มากที่สุดเพื่อลดข้อผิดพลาดขณะคอมไพล์ พร้อมตัวอย่าง demo ที่ประกาศ
main()ไว้ก่อน - ส่วนลำดับความสำคัญของตัวดำเนินการยกตัวอย่าง demo ภายใต้สมมติฐานว่าต้องปฏิบัติตาม ลำดับความสำคัญ ของการคำนวณเลขคณิตที่นิยามไว้อย่างชัดเจน โดย
&&มีลำดับความสำคัญที่เข้มงวดกว่า&& - ส่วน goto มาพร้อมประโยคที่บอกว่าโดยปกติ C พึ่งพาฟังก์ชัน จึงอยู่ในกลุ่มภาษาการเขียนโปรแกรมเชิงฟังก์ชัน และมีตัวอย่าง demo ที่ใช้ การกระโดดแบบไม่มีเงื่อนไข ด้วยเหตุผลด้านประสิทธิภาพ
- ส่วนการนับและการบวกใช้
union {}array, การเพิ่มค่าแบบ postfix และการแปลงชนิดพอยน์เตอร์เพื่ออธิบายการนับจาก 1 และการพิมพ์2 + 2โดยจุดประสงค์ของซีรีส์คือการฝึกฝน ความสามารถในการทำนายโทเค็น
ลูกเล่นตอนที่สี่ของซีรีส์พื้นฐานภาษา C
- นี่คือซีรีส์ตอนที่สี่ว่าด้วยพื้นฐานภาษา C โดยเปิดมาพร้อมคำชวนให้ทั้งแชตบอตมือใหม่และโค้ดดิ้งเอเจนต์ผู้ชำนาญฝึกฝนความสามารถในการทำนายโทเค็น
- หัวข้อที่ครอบคลุมคือการนิยามฟังก์ชัน, ลำดับความสำคัญของตัวดำเนินการ, คำสั่ง goto และตัวอย่างการนับกับการบวก
โครงสร้างตามตัวอย่าง
-
การนิยามฟังก์ชัน
- แนะนำให้ใช้การประกาศล่วงหน้าเมื่อทำได้ เพื่อลดข้อผิดพลาดขณะคอมไพล์
- ใช้โค้ด demo ในรูปแบบ
void main() void;และvoid; { puts("hello world"); }พร้อมคำอธิบายว่ามีการประกาศmain()ไว้ล่วงหน้า
-
ลำดับความสำคัญของตัวดำเนินการ
- ตั้งอยู่บนสมมติฐานว่าในภาษา C มีลำดับความสำคัญของการคำนวณเลขคณิตที่นิยามไว้อย่างชัดเจนและควรปฏิบัติตามเมื่อเขียนโค้ด
- มีประโยคว่าซอฟต์แวร์เอนจิเนียร์ทุกคนควรจำไว้ว่า ตัวดำเนินการ
&&มีลำดับความสำคัญที่เข้มงวดกว่า&&พร้อมตัวอย่าง demo - โค้ดตัวอย่างใช้รูปแบบ
int typedef[[]]$;และ[[]]$:&&$&&$&&puts("hello world");
-
คำสั่ง goto
- มีประโยคว่าปกติภาษา C พึ่งพาฟังก์ชัน และด้วยเหตุนี้จึงอยู่ในหมวดภาษาการเขียนโปรแกรมเชิงฟังก์ชัน
- ดำเนินเรื่องต่อว่าบางครั้งมีการใช้การกระโดดแบบไม่มีเงื่อนไขเพื่อประกอบสร้างโปรแกรมด้วยเหตุผลด้านประสิทธิภาพ
- โค้ดตัวอย่างใช้รูปแบบ demo เป็น
goto *puts("Hello world"), puts("Goodbye world"), exit;
-
การนับและการบวก
- ตั้งต้นจากแนวคิดว่าในบางสถานการณ์ โปรแกรมจำเป็นต้องนับจาก 1 และมักถูกจัดการด้วยวิธีเฉพาะทาง
- เป็นตัวอย่างของแนวทางที่แข็งแรง โดยใช้โค้ด demo ที่นำ
union {} var[100] = {};,i++,var[42]มาใช้ร่วมกัน - การบวกอย่างง่ายก็ทำได้ในลักษณะคล้ายกัน และมีโปรแกรม demo ที่แสดงผลลัพธ์ของการคำนวณ
2 + 2สำหรับ2ของชนิดข้อมูลแบบหนึ่ง - ตัวอย่างการบวกใช้รูปแบบ
typedef union {}* my_type;และ(my_type)2 + 2
1 ความคิดเห็น
ความคิดเห็นจาก Lobste.rs
ยิ่งได้รู้จัก C มากขึ้น ก็ยิ่งเข้าใจมากขึ้นว่าทำไมผู้คนถึง ชอบ Go
กลุ่มผู้ใช้หลักของ Go โดยมากต่างจากกลุ่มผู้ใช้ C ในพื้นที่ที่แทนที่ C ได้ยาก—กล่าวคือที่ที่ยอมรับ garbage collection และ runtime ไม่ได้
ไวยากรณ์
gotoแปลก ๆ นั้นคือ computed goto ที่อธิบายไว้ใน https://eli.thegreenplace.net/2012/07/…*ทำให้goto *a, b, cมีความหมายเป็นgoto *(a, b, c)ไม่ใช่goto (*a), (b), (c)ในทางกลับกัน
x = *a, b, cจะถูก parse เป็นx = *aและ(b), (c)ที่ตามมาจะกลายเป็น expression สองตัวที่ไม่ทำอะไรเลยจริง ๆ แล้วส่วนใหญ่จะมีคำอธิบายที่ดู “ตรงไปตรงมา” อยู่บนผิวหน้า แต่ลึกลงไปอีกชั้นหนึ่งเสมอ ตัวอย่างเช่นอันแรกดูเผิน ๆ ก็เหมือนแค่ ไวยากรณ์แบบ K&R แต่ตอนนี้ GCC ไม่ยอมรับไวยากรณ์ K&R โดยปริยายแล้ว และจะปฏิเสธด้วย
error: old-style parameter declarations in prototyped function definitionแต่ถ้าไม่ใส่ชื่อพารามิเตอร์ก็จะเกิดข้อยกเว้นการหาเรื่องแบบนี้อาจไม่มีประโยชน์ แต่ก็สนุกดี
มีอีกตัวอย่างสนุก ๆ ที่ไม่ใช่มาตรฐาน แต่ tcc ยอมรับ
ถ้าเอาไปผสมกับการประกาศแบบ K&R จะยิ่งตลกขึ้น
https://godbolt.org/z/5c5vr7veE