สวัสดีและยินดีต้อนรับกลับ
ในการบรรยายนี้ ฉันต้องการพูดเกี่ยวกับข้อผิดพลาดทั่วไปที่คุณจะทำขณะเขียนโปรแกรมในภาษาซี
สิ่งเหล่านี้บางส่วนที่คุณอาจคุ้นเคยจากความท้าทายครั้งก่อนของคุณ
และคุณเคยเจอข้อผิดพลาดเหล่านี้แล้วจริงๆ แต่เป็นข้อผิดพลาดประเภทที่พบบ่อยที่สุด
อันแรกชัดเจนมาก ไม่มีเซมิโคลอน
จำไว้ว่าข้อความทั้งหมดใน c จะลงท้ายด้วยอัฒภาค
หากคุณไม่มีมัน คอมไพเลอร์จะบ่น
ดังนั้นการใส่เครื่องหมายอัฒภาคหรือเครื่องหมายอัฒภาคหายไปทั้งหมดจึงเป็นข้อผิดพลาดทั่วไป
ในกรณีนี้ เรากำลังใส่เครื่องหมายอัฒภาคผิดตำแหน่ง
เรามีคำสั่ง if เราใส่เครื่องหมายอัฒภาคต่อท้ายคำสั่ง if
และนี่ทำให้พฤติกรรมของโปรแกรมแตกต่างไปจากเดิมอย่างสิ้นเชิง
นี้จริงจะรวบรวม
เมื่อคุณพลาดอัฒภาคและไม่ได้รวมไว้ด้วย ระบบจะไม่คอมไพล์
แต่ในกรณีนี้ ค่าของ j จะถูกตั้งค่าเป็นศูนย์เสมอ เพราะเครื่องหมายอัฒภาคบนคำสั่ง
if ถูกวางไว้
ดังนั้นเครื่องหมายอัฒภาคจึงถูกต้องสมบูรณ์ที่จะมีไว้หลังคำสั่ง if
อันที่จริงมันแสดงถึงคำสั่ง null
ดังนั้น คุณจึงไม่มีข้อผิดพลาดโดยคอมไพเลอร์
แต่สิ่งนี้จะทำให้เกิดปัญหาเพราะ j จะไม่มีวันถูกตั้งค่าเป็นศูนย์
และข้อผิดพลาดประเภทนี้สามารถเกิดขึ้นได้ทั่วไปในการวนซ้ำเช่นกัน
เมื่อคุณมีลูปและใส่เครื่องหมายอัฒภาคที่ส่วนท้ายของลูป
for จากนั้นคุณอาจมีวงเล็บปีกกา ซึ่งคุณไม่มีวงเล็บปีกกาเพราะจะมีข้อผิดพลาดหากคุณมีวงเล็บเหลี่ยม
ซึ่งพบได้บ่อยมาก
อีกอันหนึ่งทำให้เกิดความสับสนกับตัวดำเนินการเท่ากับกับตัวดำเนินการเท่ากับ
กล่าวอย่างเฉพาะเจาะจงว่าตัวดำเนินการเท่ากับเท่ากับไม่ได้เปรียบเทียบสตริง
ดังนั้นหากคุณใช้เท่ากับเท่ากับเมื่อคุณกำลังเปรียบเทียบสตริง
นั่นไม่ถูกต้อง มันจะเปรียบเทียบการอ้างอิง
แต่ถ้าคุณตั้งใจจะกำหนดค่าให้กับตัวแปรจริง
ๆ แล้วใช้ เท่ากับ เท่ากับ คุณจะมีคอมไพเลอร์
ตอนนี้ ถ้าคุณพยายามเปรียบเทียบสองรายการ เช่น จำนวนเต็มสองจำนวนภายในคำสั่ง
if และคุณใช้โอเปอเรเตอร์การมอบหมายแทน คุณจะไม่มีข้อผิดพลาดของคอมไพเลอร์ แต่นิพจน์นั้นจะประเมินว่าเป็นจริงเสมอ
ดังนั้นเมื่อคุณใช้ equals และคุณไม่ได้ใช้ equals
เท่ากับ ปกติจะทำใน if while do statement ภายในนิพจน์บูลีน
และสิ่งนี้ถูกต้อง เว้นแต่จะมีผลในการกำหนดให้กับบางสิ่งซึ่งต่างจากการดำเนินการบางอย่าง
ในตัวอย่างนี้
ถ้าเรามีถ้า a เท่ากับ 2 มันจะกำหนด 2 ให้กับ a
มันตั้งค่าเป็นจริงเสมอเพราะนั่นเป็นข้อความจริงเพราะคุณไม่เคยล้มเหลวเมื่อทำงานที่ได้รับมอบหมาย
ดังนั้น printf จึงทำงานอยู่เสมอ
สิ่งที่คุณตั้งใจจะทำตรงนี้คือบอกว่าถ้า a เท่ากับ เท่ากับ
ดังนั้นจึงเป็นเรื่องปกติมากที่ใช้ค่าเท่ากับเมื่อเทียบกับค่าเท่ากับและจะไม่มีข้อผิดพลาดของคอมไพเลอร์
ถ้าคุณใช้ equals ในสถานการณ์ที่ไม่ถูกต้อง
คุณอาจมีพฤติกรรมที่ไม่คาดคิดเช่นกัน
แต่คุณจะมีข้อผิดพลาดของคอมไพเลอร์หากคุณใช้มันเพื่อมอบหมายงานอย่างไม่ถูกต้อง
แต่ระวังสิ่งนี้ด้วยค่าเท่ากับแทนที่จะเป็นเท่ากับ
ละเว้นการประกาศต้นแบบ
ฉันกล่าวว่าสิ่งสำคัญอย่างยิ่งคือต้องประกาศฟังก์ชันของคุณที่ด้านบนสุดของไฟล์เสมอก่อนใช้งาน
อย่างไรก็ตาม สิ่งนี้ไม่ได้เกิดขึ้นเสมอไป และเป็นข้อผิดพลาดทั่วไป
และโดยปกติแล้ว สิ่งที่จะเกิดขึ้นคือคุณจะได้รับข้อผิดพลาดในการประกาศโดยนัยในคอมไพเลอร์
ในตัวอย่างนี้ ถ้าคุณมีสแควร์รูทที่กำหนดไว้ในโปรแกรมในภายหลัง
มากกว่าตำแหน่งที่คุณเรียกใช้หรือในไฟล์อื่น และคุณไม่ได้ประกาศอย่างชัดแจ้ง คุณจะต้องมีคำเตือนบางอย่าง
คอมไพเลอร์จะถือว่าฟังก์ชันส่งคืน int
การรวมการประกาศต้นแบบนั้นไว้ด้านบนสุดสำหรับฟังก์ชันทั้งหมดที่คุณเรียกใช้นั้นปลอดภัยที่สุดเสมอ
ไม่ว่าจะโดยชัดแจ้งหรือโดยปริยาย
โดยรวมไฟล์ส่วนหัวที่ถูกต้องในโปรแกรมของคุณ
แต่เมื่อคุณไม่ได้รวมไว้ การประกาศต้นแบบเหล่านั้น คุณอาจมีข้อผิดพลาดได้
ไม่สามารถรวมไฟล์ส่วนหัวที่มีคำจำกัดความสำหรับฟังก์ชันไลบรารีการเขียนโปรแกรม
c ที่ใช้ในโปรแกรม
ดังนั้น ในกรณีนี้ คุณต้องการใช้รหัสซ้ำ บางทีคุณอาจมีฟังก์ชัน printf
ที่คุณต้องการแสดงเอาต์พุต แต่คุณไม่ได้รวมไฟล์ส่วนหัว lib มาตรฐาน
นั่นเป็นความผิดพลาด และนั่นมักจะบอกคุณโดยคอมไพเลอร์
จะมีปัญหาในการเชื่อมโยงกับฟังก์ชันนั้น
ในกรณีนี้ เรามีคำตอบสองเท่า เท่ากับค่ารากที่สอง 1
หากโปรแกรมนี้ไม่รวมคณิตศาสตร์ ไฟล์ส่วนหัวนี้จะสร้างข้อผิดพลาดที่รากที่สองไม่ได้กำหนดไว้
มันจะไปลองเชื่อมโยงไฟล์อ็อบเจ็กต์ มันจะไม่มีคณิตศาสตร์ o
และมันจะบอกว่า เฮ้ คุณกำลังเรียกสแควร์รูท แต่ไม่มีการนำไปใช้
ดังนั้น อย่าลืมใส่ส่วนหัวที่ถูกต้องสำหรับการเรียกใช้ฟังก์ชันทั้งหมดของคุณ
โดยเฉพาะจากไลบรารีมาตรฐาน
สับสนค่าคงที่อักขระในสตริงอักขระ
ดังนั้น หากเรามีข้อความเท่ากับเครื่องหมายคำพูดเดียวด้านใน
นั่นคืออักขระตัวเดียวที่กำหนดให้กับข้อความ
ถ้าเรามีตัวแปรชื่อ text และเรากำหนดด้วยเครื่องหมายคำพูดคู่
นั่นคือตัวชี้ไปยังสตริงอักขระ
นั่นไม่ถูกต้องสำหรับอักขระตัวเดียว
และที่จริงแล้วเราได้พูดถึงค่าคงที่สตริงและกำหนดให้กับอาร์เรย์อักขระ
และวิธีที่คุณไม่สามารถทำอย่างนั้นกับค่าเท่ากันได้ และคุณต้องใช้มันกับสำเนารูปดาว
ในกรณีนี้ เมื่อเราพูดว่า text เท่ากับ a เป็นการกำหนดพอยน์เตอร์
ซึ่งอันที่จริงก็ใช้ไม่ได้เช่นกัน
และดูสิ่งที่คุณต้องทำคือ คุณต้องทำข้อความรูปดาวเท่ากับ
a หรือคัดลอกรูปดาว ไม่ต้องการมอบหมายโดยตรงเช่นนั้น
แต่คุณได้รับส่วนสำคัญ
การใช้ภายในของเครื่องหมายคำพูดเดี่ยวกับอักขระภายในเครื่องหมายคำพูดคู่
ต่างกันโดยสิ้นเชิง อักขระกับสตริง
ในกรณีแรก โดยปกติข้อความจะถูกประกาศให้เป็นตัวแปรอักขระ
และในกรณีที่สอง ควรประกาศให้เป็นตัวชี้ประเภทตัวอักษร
และถ้าคุณต้องการกำหนดค่าให้กับตัวชี้นั้นนอกเหนือจากตัวชี้เอง
คุณจะต้องยกเลิกการอ้างอิงตัวชี้นั้น
สิ่งนี้ไม่ถูกต้องจริง ๆ เพราะถ้าเป็นตัวชี้แทนที่จะกำหนดที่อยู่
คุณกำลังกำหนดสตริง ดังนั้นจึงไม่สมเหตุสมผล
การใช้ขอบเขตที่ไม่ถูกต้องสำหรับอาร์เรย์ ข้อยกเว้นอาร์เรย์ที่อยู่นอกขอบเขต
ในที่นี้ เรากำลังประกาศอาร์เรย์จำนวนเต็มขนาด 100 แล้วตามด้วยตัวแปร
I และผลรวมโดยมีเพียงบางตัวที่เริ่มต้นเท่านั้น
และเราวนซ้ำไปซ้ำมา เราบอกว่า I เท่ากับ 1 I น้อยกว่า 100
ไม่ถูกต้องเพราะขนาดของร้อยหมายความว่ามีองค์ประกอบนับร้อยในอาร์เรย์
แต่อาร์เรย์เป็นศูนย์
ดังนั้นองค์ประกอบแรกจึงเป็นศูนย์ ดัชนีสูงสุดที่คุณสามารถกำหนดหรือเข้าถึงในอาร์เรย์ได้คือ
99
นี่จะน้อยกว่าเท่ากับ
ดังนั้นคุณจะผิดพลาดเกินขอบเขตที่นี่
นี่ไม่ใช่ตัวห้อยที่ถูกต้องเพราะการวนซ้ำนี้กำลังจะไปถึง
100
อาจไม่ถูกต้องเช่นกันเพราะคุณเริ่มต้นที่ 1
หากคุณต้องการองค์ประกอบแรกของอาร์เรย์นี้จริงๆ คุณจะเริ่มต้นที่ 0
การลืมจองตำแหน่งพิเศษในอาร์เรย์สำหรับการยกเลิกอักขระ
null ของสตริงก็เป็นปัญหาทั่วไปเช่นกัน
เมื่อประกาศอาร์เรย์อักขระของคุณ อาร์เรย์ต้องมีขนาดใหญ่พอที่จะมีอักขระที่สิ้นสุดเพียงอย่างเดียว
นี่คือเหตุผลที่ฉันแนะนำว่าอย่าใส่ขนาดลงในอาร์เรย์เมื่อคุณสร้างมันขึ้นมา
หากคุณกำลังเริ่มต้นมัน
คุณจะใส่ขนาดเข้าไปเท่านั้นหากคุณไม่ได้เริ่มต้น
หากคุณกำลังสร้างการเริ่มต้นในบรรทัดเดียวกัน ให้ c ทำงานแทนคุณ
มันจะใส่ขนาดที่เหมาะสมโดยอัตโนมัติ และจะรวม null terminator นั้นด้วย
ตัวอย่างเช่น หากคุณมีสตริงอักขระที่เรียกว่า สวัสดี นี่เป็นตำแหน่งหน่วยความจำมากกว่า
5 ตำแหน่ง ซึ่งจะมีหกตำแหน่งเนื่องจากตัวสิ้นสุด null นั้นอยู่ที่ส่วนท้าย
อย่าลืมเกี่ยวกับขนาดของอาร์เรย์ของคุณ
นี่เป็นปัญหาทั่วไปของพอยน์เตอร์ซึ่งเรายังไม่ได้พูดคุยกันมากนัก แต่ฉันอยากจะพูดถึงเพราะมันเป็นเรื่องธรรมดามาก
ในพอยน์เตอร์ เมื่อคุณต้องการเข้าถึงหรือสั่งการ เมื่อคุณต้องการเข้าถึงบางสิ่งด้วยตัวชี้
คุณต้องใช้ขีดกลางที่มากกว่าสัญลักษณ์
ใช้เมื่อคุณเข้าถึงองค์ประกอบตัวชี้
ดังนั้นถ้าคุณมีพอยน์เตอร์ที่ชี้ไปที่โครงสร้าง นั่นคือวิธีที่คุณเข้าถึงได้
หากคุณมีโครงสร้าง ไม่ใช่ตัวชี้
คุณจึงเข้าถึงได้โดยใช้ตัวดำเนินการจุด
หลายครั้งที่ตัวดำเนินการจุดและเส้นประนี้มากกว่าจะใช้อย่างไม่ถูกต้อง
Dot สำหรับ non-pointers, pointers dash มากกว่า ซึ่งจะชัดเจนในตัวอย่างของเรามากขึ้น
การละเว้นเครื่องหมายและก่อนตัวแปรที่ไม่ใช่ตัวชี้ในการเรียก scanf
ดังนั้นโปรดจำไว้ว่าการเรียก scanf ของเราคาดหวังให้พอยน์เตอร์เป็นอาร์กิวเมนต์ที่สอง
และนั่นหมายถึงที่อยู่
เมื่อเราประกาศประเภทข้อมูลเป็นตัวแปรประเภท int นั่นไม่ใช่ตัวชี้
ดังนั้นเพื่อให้ scanf เก็บข้อมูลนั้นไว้ในตัวแปร int ของเรา เราต้องส่งเครื่องหมายและเพื่อบอกว่ามันคือที่อยู่
ดังนั้นนี่จึงไม่ถูกต้อง ไม่มีเครื่องหมายและนำหน้าตัวเลขและสแกน
f เนื่องจากอาร์กิวเมนต์ที่สองไม่ถูกต้อง
ครั้งเดียวที่คุณไม่มีเครื่องหมายและคือถ้าคุณใช้ตัวชี้
เช่น อาร์เรย์อักขระ
อาร์กิวเมนต์ทั้งหมดที่ปรากฏหลังสตริงรูปแบบและ scanf ต้องเป็นพอยน์เตอร์
การใช้ตัวแปรพอยน์เตอร์ก่อนที่จะเริ่มต้น
นี่คือตัวอย่างการสร้างพอยน์เตอร์แล้วพยายามกำหนดให้กับมัน
และนี่คือการมอบหมายที่ถูกต้องซึ่งคุณกำลังกำหนดค่าที่คุณไม่ได้อ้างอิง
แต่สิ่งที่เรายังไม่ได้ทำในที่นี้คือ เราได้เริ่มต้นตัวชี้เพื่อให้มีหน่วยความจำที่จัดสรรไว้สำหรับมันแล้ว
และคุณไม่สามารถทำได้ใน c
คุณสามารถใช้ได้เฉพาะตัวดำเนินการทางอ้อม ซึ่งเป็นเครื่องหมายดอกจันที่อยู่ข้างหน้ากับจุดหรือตัวแปรหลังจากที่คุณตั้งค่าตัวแปรให้ชี้ไปที่ใดที่หนึ่งแล้ว
ดังนั้นมันต้องชี้ไปที่ใดที่หนึ่ง ตอนนี้ มันไม่ชี้ไปที่ใดเลย เพราะคุณไม่ได้จัดสรรหน่วยความจำใดๆ
ดังนั้นตัวชี้อักขระจึงไม่เคยตั้งค่าให้ชี้ไปที่สิ่งใด ดังนั้นการมอบหมายจึงไม่มีความหมาย
สิ่งนี้จะทำให้เกิดข้อผิดพลาดในการแบ่งส่วน
ข้อผิดพลาดทั่วไปอีกประการหนึ่งคือการละเว้นคำสั่ง break ที่ส่วนท้ายของเคสในคำสั่ง switch
หากไม่รวมการแบ่งที่ส่วนท้ายของเคส การดำเนินการจะดำเนินการต่อไปในเคสถัดไป
นี่คือสิ่งที่ผมพูดถึงในกรณีที่คุณมีคดี มันจะได้รับการประเมิน
และถ้าคุณไม่มีช่องโหว่นั้น มันจะไปต่อในเคสถัดไปและรันโค้ดในกรณีถัดไป
ดังนั้นคุณจึงต้องการแบ่งคำแถลงกรณีของคุณเสมอ
มีบางครั้งที่คุณต้องการให้มีการติดตามกรณีอื่นและพวกเขาทำในสิ่งเดียวกัน
ในกรณีนี้ คุณจะไม่มีอะไรอยู่ภายในคำสั่งของกรณี
การแทรกเซมิโคลอนที่ส่วนท้ายของนิยามตัวประมวลผลล่วงหน้า
คำจำกัดความของตัวประมวลผลล่วงหน้าจะขึ้นต้นด้วยตัวเลข
สัญลักษณ์ปอนด์ ตัวประมวลผลล่วงหน้าจะถูกรันก่อนคอมไพเลอร์เพื่อการปรับให้เหมาะสม
ไวยากรณ์ที่ถูกต้องสำหรับคำจำกัดความของตัวประมวลผลล่วงหน้านั้นไม่ต้องรวมอัฒภาค
อย่างไรก็ตาม ใน c คุณ ให้ติดเป็นนิสัยโดยใส่เครื่องหมายอัฒภาคตามหลังทุกอย่าง
แต่คุณต้องจำไว้ว่าถ้าคุณกำหนดข้อมูลคงที่บางอย่างที่คุณไม่ต้องการเซมิโคลอน
สิ่งนี้ไม่ถูกต้อง
สิ่งนี้จะนำไปสู่ข้อผิดพลาดทางไวยากรณ์หากใช้นิพจน์เช่นนั้น
เช่นนั้น. ดังนั้นหากคุณพยายามใช้สิ่งนั้นเพื่อค้นหา
การใส่เครื่องหมายอัฒภาคต่อท้ายก็ไม่เป็นไร
แต่เมื่อตัวประมวลผลล่วงหน้าทำงาน มันจะแทรกสิ่งที่อยู่ในที่กำหนดไว้อย่างแน่นอน
มันจะไปต่อท้าย data 999 โคลอน
นี่คือสิ่งที่คอมไพเลอร์จะได้เห็น และมันจะทำให้เกิดข้อผิดพลาดจริง ๆ ซึ่งจะเป็นข้อผิดพลาดทางไวยากรณ์
การละเว้นวงเล็บปิดหรือเครื่องหมายอัญประกาศปิดในคำสั่งใดๆ
เป็นเรื่องปกติมาก ดังนั้นสิ่งนี้จึงเกี่ยวข้องโดยตรงกับวงเล็บปีกกาเช่นกัน
โดยมีวงเล็บปีกกาเริ่มต้นและไม่สิ้นสุดวงเล็บปีกกา เช่นเดียวกับวงเล็บ
ในกรณีนี้
เรามีวงเล็บซ้ายเริ่มต้นสองวงเล็บหรือสามวงเล็บ แต่เรามีเพียงวงเล็บปิดท้ายสองอันเท่านั้น
เราไม่มีวงเล็บปิดท้ายด้านขวา
นั่นจะเป็นข้อผิดพลาดทางไวยากรณ์ที่คอมไพเลอร์จะพบ
ดังนั้นเมื่อคุณใช้การฝังในวงเล็บเพื่อแยกส่วนของสมการออกจากกัน จะทำให้บรรทัดโค้ดอ่านง่ายขึ้น
คุณต้องการใช้วงเล็บ
อย่างไรก็ตาม คุณต้องการทำให้แน่ใจว่าทุกอันตรงกัน
คุณเริ่มวงเล็บ คุณต้องมีวงเล็บปิดท้าย เช่นเดียวกับวงเล็บปีกกา
คุณเริ่มเฝือกดัดงอ ก็ต้องเฝือกดัดปลาย
ดังนั้นไม่ว่าคุณจะมีมากเกินไปหรือมีน้อยเกินไป
แต่คอมไพเลอร์กำลังจะบ่น และนี่เป็นเรื่องธรรมดามาก
ดังนั้นบรรทัดที่สองที่นี่จึงไม่มีเครื่องหมายอัญประกาศปิดเช่นกัน คำสั่งพิมพ์นี้
เราไม่มีใบเสนอราคาสิ้นสุด
คอมไพเลอร์จะบ่นเกี่ยวกับเรื่องนั้น
ทั้งสองสิ่งนี้จะสร้างข้อผิดพลาดในการคอมไพล์
บางครั้งแม้ว่าคอมไพเลอร์จะทำให้เข้าใจผิดมากเพราะไม่รู้ว่าข้อผิดพลาดเกิดขึ้นที่ใด
คิดว่าข้อผิดพลาดอาจเกิดขึ้นในบรรทัดถัดไป
ดังนั้นบรรทัดที่แจ้งข้อผิดพลาดอาจทำให้เข้าใจผิด
ดังนั้นขึ้นอยู่กับว่าคอมไพเลอร์ใช้วงเล็บหรือเครื่องหมายคำพูดในบรรทัดถัดไป
จะทำให้นิพจน์นั้นสมบูรณ์
ดังนั้นจะย้ายข้อผิดพลาดลงไปอีกบรรทัดหนึ่ง
และนั่นคือสิ่งที่มันจะบ่นและบอกว่านั่นคือที่ที่ข้อผิดพลาดอยู่ แต่ข้อผิดพลาดที่แท้จริงนั้นสูงกว่าตำแหน่งที่คุณต้องการวาง
นี่เป็นข้อผิดพลาดทั่วไปที่ฉันเห็นโปรแกรมเมอร์ C จำนวนมากทำ
ง่ายต่อการแก้ไข และถ้าคุณเข้าใจและศึกษาสิ่งนี้
คุณก็จะรู้ว่าไม่ควรสร้างมันขึ้นมา
ไม่เป็นไรที่จะทำให้มันเป็นมือใหม่
แต่เมื่อคุณเขียนโค้ดมากขึ้นเรื่อย ๆ และฝึกฝนมากขึ้น
คุณจะรู้ว่า เฮ้ ฉันลืมวงเล็บ ลืมวงเล็บ ฉันไม่ได้ใช้อีควอไลเซอร์และอีควอไลซ์ให้ถูกต้อง
ฉันใช้พอยน์เตอร์ไม่ถูกต้อง ฉันไม่ได้จัดสรรหน่วยความจำใดๆ
สิ่งเหล่านี้จะมีลักษณะที่สองมากขึ้น ขอขอบคุณ.