อะไรคือแนวคิด / เทคนิค / คุณสมบัติภาษาที่โปรแกรมเมอร์ C ที่ดีทุกคนควรรู้ / ระวัง (ไม่รวมวิศวกรรมซอฟต์แวร์ทั่วไปและลักษณะที่คล้ายกัน ฉันต้องการทราบเพื่อที่ฉันจะได้สามารถเติมเต็มช่องว่างที่เป็นไปได้ในความรู้ C ของฉัน
2 + 2 = 4
อะไรคือแนวคิด / เทคนิค / คุณสมบัติภาษาที่โปรแกรมเมอร์ C ที่ดีทุกคนควรรู้ / ระวัง (ไม่รวมวิศวกรรมซอฟต์แวร์ทั่วไปและลักษณะที่คล้ายกัน ฉันต้องการทราบเพื่อที่ฉันจะได้สามารถเติมเต็มช่องว่างที่เป็นไปได้ในความรู้ C ของฉัน
2 + 2 = 4
คำตอบ:
เฉพาะ C? นอกเหนือจากการสร้างมาตรฐานทั่วไปภาษาขั้นตอนส่วนใหญ่ฉันต้องพูดว่า:
ทำความเข้าใจกับพอยน์เตอร์และคุณจะเข้าใจคอมพิวเตอร์
นอกจากคำตอบที่ยอดเยี่ยมของ pythagras แล้ว
วิธีการเขียน (หรืออย่างน้อยอ่าน) การประกาศที่ซับซ้อนเช่น char (*(*funcs[4])())[10]
funcs คืออาร์เรย์ [4] ของพอยน์เตอร์ไปยังฟังก์ชันที่ส่งคืนพอยน์เตอร์ไปยังอาร์เรย์ [10] ของถ่าน
โปรแกรมเมอร์ AC ควรรู้ ... ภาษาอื่น ๆ ! ;-) การรู้แนวคิดจากภาษาอื่น ๆ ในกระบวนทัศน์ที่หลากหลายเช่น OOP การเขียนโปรแกรมที่ใช้งานได้และอื่น ๆ
อย่างจริงจังยิ่งขึ้นการดูการประกวดการเขียนโปรแกรมที่สับสนนั้นสนุกและอยากรู้อยากเห็นเป็นประสบการณ์ที่ดีเช่นกัน
ฉันพูดถึง "buffer overflows" ในความคิดเห็นต่อคำตอบของ Pythagras ฉันอาจจะอธิบายสิ่งที่ฉันหมายถึงเล็กน้อย ใน C ไม่เพียงพอที่จะรู้ว่าการทำงานกับหน่วยความจำโดยตรงนั้นเป็นอันตราย - คุณควรเข้าใจวิธีการที่แม่นยำซึ่งเป็นอันตราย ฉันไม่ชอบคำอุปมา "ยิงตัวเองในเท้า" สำหรับทุกกรณี - หลายครั้งคุณไม่ได้เหนี่ยวไก แต่บ่อยครั้งที่มันเป็นนักแสดงที่มีความสนใจตรงข้ามกับคุณและ / หรือผู้ใช้ของคุณ .
ตัวอย่างเช่นในสถาปัตยกรรมที่มีสแต็กจากมากไปน้อย (สถาปัตยกรรมที่นิยมมากที่สุดพอดีกับบิลนี้ - x86 และ ARM โดยทั่วไปรวมอยู่) เมื่อคุณเรียกใช้ฟังก์ชันที่อยู่ผู้ส่งคืนสำหรับฟังก์ชันจะถูกวางไว้บนสแต็กหลังจากตัวแปรท้องถิ่นที่กำหนดไว้ใน ร่างกายของฟังก์ชั่น ดังนั้นหากคุณประกาศบัฟเฟอร์เป็นตัวแปรท้องถิ่นและเปิดเผยตัวแปรนั้นกับโลกภายนอกโดยไม่ตรวจสอบบัฟเฟอร์ล้นเช่นนี้
void myFn(void) {
char buf[256];
gets(buf);
}
ผู้ใช้ภายนอกสามารถส่งสตริงที่เขียนทับที่อยู่ผู้ส่งคืนจากสแต็ก - โดยทั่วไปเขาสามารถเปลี่ยนแนวคิดการเรียกใช้เวลาทำงานของโปรแกรมของคุณสำหรับกราฟการโทรที่นำไปสู่ฟังก์ชันปัจจุบัน ดังนั้นผู้ใช้จะให้สตริงที่เป็นตัวแทนไบนารีของโค้ดที่ประมวลผลได้บางอย่างสำหรับสถาปัตยกรรมของคุณ, การขยายตัวมากพอที่จะล้นสแต็คจากmyFn
, และข้อมูลเพิ่มเติมบางอย่างเพื่อเขียนทับที่อยู่ผู้ส่งกลับสำหรับmyFn
ชี้ไปที่รหัสที่เขามอบให้คุณ หากสิ่งนี้เกิดขึ้นเมื่อmyFn
ปกติแล้วจะส่งคืนการควบคุมไปยังผู้เรียกมันจะเปลี่ยนเป็นรหัสที่ผู้ใช้ประสงค์ร้ายให้แทน หากคุณเขียนรหัส C (หรือ C ++) ที่มีศักยภาพที่จะเปิดเผยต่อผู้ใช้ที่ไม่น่าเชื่อถือคุณต้องเข้าใจเวกเตอร์การโจมตีนี้. คุณควรเข้าใจว่าเหตุใดบัฟเฟอร์ล้นกับสแต็กมักจะใช้ประโยชน์ได้ง่ายกว่ากองกับกองซ้อนและคุณควรเข้าใจว่าหน่วยความจำในกองวาง (ไม่ได้อยู่ในรายละเอียดมากเกินไปจำเป็น แต่ แนวคิดที่ว่าmalloc()
ภูมิภาค 'ed มีโครงสร้างการควบคุมโดยรอบสามารถช่วยให้เข้าใจได้ว่าเหตุใดโปรแกรมของคุณจึงล้มเหลวในอีกmalloc()
หรือในfree()
)
C ทำให้คุณมีรายละเอียดในระดับต่ำเกี่ยวกับการทำงานของเครื่องและช่วยให้คุณสามารถควบคุมเครื่องของคุณได้โดยตรงมากกว่าภาษาที่ผู้ใช้แก้ไขอื่น ๆ ที่ใช้กันอย่างแพร่หลายในปัจจุบัน ด้วยพลังอันยิ่งใหญ่มาพร้อมความรับผิดชอบที่ยิ่งใหญ่ - คุณต้องเข้าใจรายละเอียดในระดับต่ำจริง ๆ เพื่อที่จะทำงานกับ C ได้อย่างปลอดภัยและมีประสิทธิภาพ
นอกเหนือจากคำตอบที่ดีอื่น ๆ ฉันต้องการเพิ่ม เทคนิคการเขียนโปรแกรมป้องกันลงในรายการ
เช่นการใช้ asserts เมื่อเริ่มต้น / สิ้นสุดฟังก์ชั่นเพื่อตรวจสอบสัญญา