[สำหรับบันทึกฉันได้แก้ไขคำตอบนี้ค่อนข้างมากเนื่องจากได้รับการยอมรับและโหวตให้ มันยังบอกว่าโดยพื้นฐานแล้วสิ่งเดียวกันแม้ว่า]
รหัสนี้มีความลึกและอาจทำให้เกิดความสับสน มันมีตัวอย่างหวุดหวิดหันไปของความหวาดกลัวไม่ได้กำหนดพฤติกรรม โดยทั่วไปแล้วเป็นไปไม่ได้ที่จะตัดสินว่าคนที่สร้างคำถามนี้เป็นคนที่ฉลาดเฉลียวหรือโง่มาก และ "บทเรียน" รหัสนี้อาจอ้างถึงการสอนหรือตอบคำถามเกี่ยวกับคุณ - นั่นคือผู้ดำเนินการยูนารีบวกไม่ได้ทำอะไรมาก - แน่นอนว่ามันไม่สำคัญพอที่จะสมควรได้รับทิศทางที่ถูกโค่นล้มแบบนี้
โค้ดมีสองด้านที่ทำให้เกิดความสับสนเงื่อนไขแปลก ๆ :
while(+(+k--)!=0)
และคำสั่งที่บ้าคลั่งมันควบคุม:
k=k++;
ฉันจะครอบคลุมส่วนที่สองก่อน
หากคุณมีตัวแปรแบบkที่คุณต้องการเพิ่มขึ้น 1, C จะให้คุณไม่ใช่หนึ่งไม่ใช่สองไม่ใช่สาม แต่สี่วิธีที่แตกต่างกัน:
k = k + 1
k += 1
++k
k++
แม้จะมีความโปรดปรานนี้ (หรืออาจเป็นเพราะมัน) แต่โปรแกรมเมอร์บางคนก็สับสน
k = k++;
หากคุณไม่สามารถเข้าใจได้ว่าควรทำอย่างไรไม่ต้องกังวล: ไม่มีใครทำได้ นิพจน์นี้มีความพยายามที่แตกต่างกันสองครั้งเพื่อแก้ไขkค่าของ ( k =ส่วนและk++ส่วน) และเนื่องจากไม่มีกฎใน C ที่จะบอกว่าการปรับเปลี่ยนใดที่พยายาม "ชนะ" การแสดงออกเช่นนี้ไม่ได้กำหนดอย่างเป็นทางการซึ่งไม่เพียง มันไม่มีความหมายที่กำหนด แต่โปรแกรมทั้งหมดที่มีมันเป็นผู้ต้องสงสัย
ตอนนี้ถ้าคุณมองมากอย่างคุณจะเห็นว่าในโปรแกรมนี้โดยเฉพาะอย่างยิ่งสายk = k++ไม่จริงจะได้รับการดำเนินการเพราะ (ในขณะที่เรากำลังจะดู) สภาพการควบคุมเป็นเท็จแรกดังนั้นห่วงวิ่ง 0 ครั้ง . ดังนั้นโปรแกรมเฉพาะนี้อาจไม่ได้ไม่ได้กำหนดจริง ๆแต่ก็ยังมีความสับสนทางพยาธิวิทยา
ดูเพิ่มเติมที่บัญญัติเหล่านี้เพื่อตอบคำถามทุกข้อเกี่ยวกับพฤติกรรมที่ไม่ได้กำหนดของประเภทนี้
แต่คุณไม่ได้ถามเกี่ยวกับk=k++ส่วนนี้ คุณถามเกี่ยวกับส่วนที่สับสนแรก+(+k--)!=0เงื่อนไข นี้มีลักษณะแปลกเพราะมันเป็นที่แปลกประหลาด ไม่มีใครเคยเขียนโค้ดดังกล่าวในโปรแกรมจริง ดังนั้นจึงไม่มีเหตุผลที่จะเรียนรู้วิธีทำความเข้าใจ (ใช่มันจริงการสำรวจขอบเขตของระบบสามารถช่วยให้คุณเรียนรู้เกี่ยวกับจุดที่ดีของมัน แต่มีเส้นที่ชัดเจนในหนังสือของฉันระหว่างการสำรวจเชิงจินตนาการการกระตุ้นความคิดและการสำรวจที่ผิดปกติทารุณและการแสดงออกที่ชัดเจนมาก ด้านที่ผิดของบรรทัดนั้น)
+(+k--)!=0อย่างไรก็ตามขอตรวจสอบ (และหลังจากทำเช่นนั้นมาลืมเรื่องทั้งหมด) การแสดงออกเช่นนี้จะต้องเข้าใจจากภายในสู่ภายนอก ฉันเข้าใจว่าคุณรู้อะไร
k--
ทำ. มันต้องใช้kค่าปัจจุบัน 's และ 'ผลตอบแทน' มันกับส่วนที่เหลือของการแสดงออกและมันมากหรือน้อยพร้อมกัน decrements k, ที่อยู่, จะเก็บปริมาณกลับเข้ามาk-1k
แต่แล้วจะ+ทำอย่างไร? นี่คือunary plus ไม่ใช่ไบนารีบวก มันก็เหมือนกับการลบนารี คุณรู้ว่าลบด้วยเลขฐานสองจะลบ: การแสดงออก
a - b
ลบ b จาก a และคุณรู้ว่าเอกนารีลบล้างสิ่งต่าง ๆ นั่นคือการแสดงออก
-a
ให้ลบ a สิ่งที่แตกต่างกัน+คือ ... โดยพื้นฐานแล้วไม่มีอะไร +aให้aคุณค่ากับคุณหลังจากเปลี่ยนค่าบวกเป็นค่าบวกและลบเป็นลบ ดังนั้นการแสดงออก
+k--
ให้สิ่งที่k--ให้แก่คุณนั่นคือkคุณค่าเก่า ๆ
แต่เราไม่ได้ทำเพราะเรามี
+(+k--)
สิ่งนี้จะนำสิ่งใดมา+k--ให้คุณและนำไปใช้กับ unary +อีกครั้ง ดังนั้นมันจะให้อะไรก็ตามที่+k--ให้คุณซึ่งเป็นสิ่งที่k--ให้คุณซึ่งเป็นkคุณค่าเก่าแก่
ดังนั้นในที่สุดสภาพ
while(+(+k--)!=0)
ทำสิ่งเดียวกันเป็นเงื่อนไขปกติมากขึ้น
while(k-- != 0)
จะได้ทำ (มันยังทำในสิ่งเดียวกันกับสภาพที่ดูซับซ้อนมากขึ้นwhile(+(+(+(+k--)))!=0)และวงเล็บก็ไม่จำเป็นเช่นกันมันก็ทำเช่นเดียวกันกับที่while(+ + + +k--!=0)ทำไป)
แม้แต่การหาเงื่อนไขว่า "ปกติ"
while(k-- != 0)
ไม่ยุ่งยาก มีสองสิ่งที่เกิดขึ้นในวงนี้: เมื่อวงวนอาจเกิดขึ้นหลายครั้งเราจะไปที่:
- ทำ
k--ต่อไปเพื่อให้kเล็กลงและเล็กลง แต่ยัง
- ทำร่างกายของห่วงไม่ว่าอะไรก็ตาม
แต่เราทำk--ส่วนทันทีก่อน (หรือในกระบวนการ) ตัดสินใจว่าจะเดินทางอีกครั้งผ่านวง และจำไว้ว่าk--"คืนค่า" ค่าเก่าของkก่อนที่จะลดค่าลง ในโปรแกรมนี้ค่าเริ่มต้นkคือ 0 ดังนั้นk--จะ "คืน" ค่าเก่า 0 จากนั้นอัพเดทkเป็น -1 แต่เงื่อนไขที่เหลือคือ!= 0- แต่อย่างที่เราเพิ่งเห็นครั้งแรกที่เราทดสอบเงื่อนไขเราได้ 0 ดังนั้นเราจะไม่ทำการเดินทางผ่านลูปดังนั้นเราจะไม่พยายามดำเนินการ คำสั่งที่มีปัญหาk=k++ที่ทุกคน
กล่าวอีกนัยหนึ่งในวงเฉพาะนี้แม้ว่าฉันจะบอกว่า "มีสองสิ่งที่เกิดขึ้น" ปรากฎว่าสิ่งที่ 1 เกิดขึ้นครั้งเดียว แต่สิ่งที่ 2 เกิดขึ้นเป็นศูนย์ครั้ง
ในอัตราใด ๆ ฉันหวังว่ามันตอนนี้เพียงพอที่ชัดเจนว่าทำไมนี้ข้ออ้างที่ดีสำหรับโปรแกรมสิ้นสุดการพิมพ์ -1 kเป็นค่าสุดท้ายของ โดยปกติแล้วฉันไม่ชอบตอบคำถามในแบบทดสอบนี้ - มันรู้สึกเหมือนการโกง - แต่ในกรณีนี้เนื่องจากฉันไม่เห็นด้วยอย่างมากกับประเด็นทั้งหมดของการออกกำลังกายฉันไม่รังเกียจ