ทำไมเรามีการเพิ่ม postfix?


55

ข้อจำกัดความรับผิดชอบ : ฉันรู้ดีว่าความหมายของคำนำหน้าและการเพิ่มคำนำหน้า ดังนั้นโปรดอย่าอธิบายให้ฉันฟังว่ามันทำงานอย่างไร

การอ่านคำถามเกี่ยวกับการโอเวอร์โฟลว์ของสแต็คฉันไม่สามารถช่วยได้ แต่สังเกตว่าโปรแกรมเมอร์สับสนโดยผู้ประกอบการเพิ่ม postfix ซ้ำแล้วซ้ำอีก จากคำถามนี้จะเกิดขึ้น: มีกรณีการใช้งานใดบ้างที่การเพิ่ม postfix ให้ประโยชน์ที่แท้จริงในแง่ของคุณภาพของรหัส?

ให้ฉันอธิบายคำถามของฉันด้วยตัวอย่าง นี่คือการใช้งานแบบย่อของstrcpy:

while (*dst++ = *src++);

แต่นั่นไม่ใช่รหัสการจัดทำเอกสารด้วยตัวเองที่แน่นอนที่สุดในหนังสือของฉัน (และมันสร้างคำเตือนที่น่ารำคาญสองประการในคอมไพเลอร์สติ) ดังนั้นมีอะไรผิดปกติกับทางเลือกต่อไปนี้?

while (*dst = *src)
{
    ++src;
    ++dst;
}

จากนั้นเราสามารถกำจัดการมอบหมายที่สับสนในสภาพและรับรหัสที่ไม่มีการเตือนอย่างสมบูรณ์:

while (*src != '\0')
{
    *dst = *src;
    ++src;
    ++dst;
}
*dst = '\0';

(ใช่ฉันรู้srcและdstจะมีค่าสิ้นสุดที่แตกต่างกันในโซลูชันทางเลือกเหล่านี้ แต่เนื่องจากstrcpyผลตอบแทนทันทีหลังจากลูปจึงไม่สำคัญในกรณีนี้)

ดูเหมือนว่าจุดประสงค์ของการเพิ่ม postfix คือการสร้างโค้ดให้สั้นที่สุด ฉันเพียงแค่ล้มเหลวที่จะเห็นว่านี่คือสิ่งที่เราควรพยายาม หากนี่เป็นเรื่องเกี่ยวกับประสิทธิภาพ แต่ยังคงมีความเกี่ยวข้องในวันนี้


7
ตัวแปร postfix นั้นเป็นตัวแปรที่ใช้กันมากที่สุดดังนั้นหากคุณกำลังจะทำคดีกับมันควรเป็นกรณีที่ค่อนข้างแข็งแกร่ง และตัวอย่างแรกของคุณเป็นคนฟางเพราะฉันสงสัยว่าบางคนจะเขียนรหัสstrcpyวิธีด้วยวิธีนี้ (ด้วยเหตุผลที่คุณพูดถึงไปแล้ว)
Robert Harvey

4
ทำไมมีทั้งที่?
James McNellis

31
หากเราลบทุกอย่างออกจากภาษาที่มีศักยภาพที่จะสร้างความสับสนให้โปรแกรมเมอร์เราจะไม่มีคุณสมบัติมากมาย บางสิ่งบางอย่างความเป็นจริงไม่ได้เป็นประโยชน์กับคุณหรือเพียงมากไม่ค่อยมีประโยชน์ไม่ได้หมายความว่ามันควรจะ snipped ถ้ามันไม่เกี่ยวข้องอีกต่อไปอย่าใช้มัน ตอนจบ.
Cody Grey

4
ใช่ แต่คุณไม่สามารถทำได้int c = 0; c++;
Biff MaGriff

4
@Cody: เพราะบางสิ่งมีทั้งความสับสนและมีประโยชน์ เขาไม่ได้สับสนโดยการเพิ่มจำนวนโพสต์เองเขาสับสนเกี่ยวกับประโยชน์ที่ได้รับ เราไม่ควรมีสิ่งที่ไร้ประโยชน์สับสนหรือไม่
GManNickG

คำตอบ:


23

ในขณะที่มันเคยมีผลกระทบต่อประสิทธิภาพการทำงานบางอย่างฉันคิดว่าเหตุผลที่แท้จริงคือการแสดงเจตนาของคุณอย่างหมดจด คำถามจริงคือสิ่งที่while (*d++=*s++);แสดงเจตนาชัดเจนหรือไม่ IMO ทำและฉันพบทางเลือกที่คุณเสนอให้ชัดเจนน้อยลง - แต่นั่นอาจเป็นผลมาจากการใช้เวลาหลายสิบปีในการทำความคุ้นเคยกับวิธีการทำสิ่งต่าง ๆ ต้องเรียนรู้ C จาก K & R (เพราะมีอยู่เกือบจะไม่มีหนังสือเล่มอื่น ๆ ในซีในเวลานั้น) อาจช่วยเกินไป

มันเป็นเรื่องจริงที่ความทรหดนั้นมีค่ามากกว่ารหัสที่เก่ากว่ามาก โดยส่วนตัวแล้วฉันคิดว่านี่เป็นสิ่งที่ดีเป็นส่วนใหญ่ - การทำความเข้าใจกับโค้ดไม่กี่บรรทัดนั้นเป็นเรื่องเล็กน้อย สิ่งที่ยากคือการเข้าใจโค้ดขนาดใหญ่ การทดสอบและการศึกษาได้แสดงซ้ำ ๆ ว่าการปรับรหัสทั้งหมดบนหน้าจอในครั้งเดียวเป็นปัจจัยสำคัญในการทำความเข้าใจรหัส เมื่อหน้าจอขยายขึ้นสิ่งนี้ดูเหมือนว่าจะเป็นจริงดังนั้นการรักษาโค้ดให้สั้น (สมเหตุสมผล) จึงเป็นสิ่งที่มีค่า

แน่นอนว่าเป็นไปได้ที่จะลงน้ำ แต่ฉันไม่คิดว่าจะเป็นเช่นนั้น โดยเฉพาะฉันคิดว่ามันเกินความจริงเมื่อการทำความเข้าใจโค้ดหนึ่งบรรทัดกลายเป็นเรื่องยากมากหรือใช้เวลานานโดยเฉพาะเมื่อการทำความเข้าใจโค้ดที่น้อยกว่านั้นจะใช้ความพยายามมากกว่าการทำความเข้าใจกับบรรทัดอื่น ๆ นั่นเป็นเรื่องปกติใน Lisp และ APL แต่ดูเหมือนจะไม่เป็นอย่างนั้น (อย่างน้อยสำหรับฉัน)

ฉันกังวลน้อยลงเกี่ยวกับคำเตือนของคอมไพเลอร์ - เป็นประสบการณ์ของฉันที่คอมไพเลอร์จำนวนมากปล่อยคำเตือนที่ไร้สาระอย่างสมบูรณ์เป็นประจำ ในขณะที่ฉันคิดว่าผู้คนควรเข้าใจรหัสของพวกเขา (และคำเตือนใด ๆ ที่อาจเกิดขึ้น) รหัสที่เหมาะสมที่เกิดขึ้นเพื่อกระตุ้นการเตือนในคอมไพเลอร์บางอย่างไม่จำเป็นต้องผิด เป็นที่ยอมรับว่าผู้เริ่มต้นไม่ทราบว่าพวกเขาสามารถเพิกเฉยได้อย่างปลอดภัยเสมอไป แต่เราไม่ได้อยู่กับผู้เริ่มต้นตลอดไปและไม่จำเป็นต้องมีรหัสเช่นเดียวกับเรา


12
+1 สำหรับการชี้ให้เห็นว่าเวอร์ชันสั้น ๆ นั้นง่ายต่อการอ่านสำหรับเราบางคน :-)

1
หากคุณไม่ชอบคำเตือนคอมไพเลอร์ของคุณ (และมีมากกว่าสองสามอย่างที่ฉันสามารถทำได้โดยไม่ต้อง - อย่างจริงจังฉันหมายถึงพิมพ์if(x = y)ฉันสาบาน!) คุณควรปรับตัวเลือกคำเตือนของคอมไพเลอร์ของคุณเพื่อให้คุณไม่พลาด คำเตือนที่คุณไม่ชอบ

4
@Brooks โมเสสฉันมากน้อยกระตือรือร้นเกี่ยวกับว่า ฉันไม่ชอบการทำให้รหัสของฉันสกปรกเพื่อชดเชยข้อบกพร่องของคอมไพเลอร์
Jerry Coffin

1
@Jerry, @Chris: คำอธิบายประกอบนี้มีไว้สำหรับกรณีที่คุณคิดว่าคำเตือนมักจะเป็นสิ่งที่ดีแต่คุณไม่ต้องการให้มันใช้กับบางบรรทัดที่ทำสิ่งผิดปกติ หากคุณไม่ต้องการคำเตือนและพิจารณาว่าเป็นข้อบกพร่องใช้-Wno-Xแต่ถ้าคุณต้องการยกเว้นเพียงข้อเดียวและต้องการให้คำเตือนใช้ทุกที่อื่น ๆ นี่เป็นสิ่งที่เข้าใจได้ง่ายกว่าการใช้การกระโดดแบบลับ ๆ เช่นคริสอ้างถึง .

1
@Brooks: เครื่องหมายวงเล็บคู่และคำสั่ง(void)xto to silence ที่ไม่ได้ใช้นั้นเป็นคำที่รู้จักกันดีในการปิดคำเตือนที่มีประโยชน์ คำอธิบายประกอบดูเหมือนเล็กน้อยpragmasไม่พกพาได้ดีที่สุด: /
Matthieu M.

32

มันคือเรื่องของฮาร์ดแวร์


ที่น่าสนใจที่คุณจะสังเกตเห็น การเพิ่มขึ้นของ Postfix อาจมีสาเหตุหลายประการที่สมบูรณ์แบบ แต่เช่นเดียวกับหลาย ๆ สิ่งใน C ความนิยมนั้นสามารถสืบย้อนไปถึงที่มาของภาษาได้

แม้ว่า C ได้รับการพัฒนาบนเครื่องที่หลากหลายและเร็วกว่า แต่ C และ Unix ได้รับผลกระทบครั้งใหญ่เมื่อเทียบกับรุ่นที่มีการจัดการหน่วยความจำของ PDP-11 เหล่านี้เป็นเครื่องคอมพิวเตอร์ที่ค่อนข้างมีความสำคัญในวันของพวกเขาและ Unix คือโดยไกลที่ดีกว่า - ชี้แจงดีกว่า - กว่าที่อื่น ๆ 7 ระบบปฏิบัติการ crummy ใช้ได้สำหรับ -11

และมันก็เกิดขึ้นเช่นนั้นใน PDP-11

*--p

และ

*p++

... ถูกนำมาใช้ในฮาร์ดแวร์เป็นโหมดที่อยู่ ( *pแต่ไม่มีการรวมกันอื่น ๆ ) ในเครื่องรุ่นแรก ๆ ทั้งหมดน้อยกว่า0.001 GHzการบันทึกคำสั่งหรือสองครั้งในลูปต้องเกือบเป็นวินาทีต่อวินาทีหรือรอเป็นนาทีหรือออกไปเพื่อ ความแตกต่าง -lunch สิ่งนี้ไม่ได้พูดถึงการทำ postincrement อย่างแม่นยำ แต่การวนซ้ำที่มีการทำ postincrement อาจทำได้ดีกว่าการทำดัชนีในตอนนั้น

เป็นผลให้รูปแบบการออกแบบเพราะสำนวน C ซึ่งกลายเป็นมาโครจิต C

มันเหมือนกับการประกาศตัวแปรหลังจาก{... ไม่ใช่เพราะ C89 เป็นกระแสได้สิ่งนี้เป็นข้อกำหนด แต่ตอนนี้มันเป็นรูปแบบโค้ด

อัปเดต:เห็นได้ชัดว่าสาเหตุหลัก*p++คือในภาษาเพราะมันเป็นสิ่งที่คนมักต้องการทำ ความนิยมของรูปแบบรหัสได้รับการเสริมด้วยฮาร์ดแวร์ที่ได้รับความนิยมซึ่งมาพร้อมกับรูปแบบของภาษาที่มีอยู่แล้วซึ่งได้รับการออกแบบเล็กน้อยก่อนที่จะมาถึงของ PDP-11

วันนี้มันทำให้ความแตกต่างซึ่งรูปแบบที่คุณใช้หรือถ้าคุณใช้การจัดทำดัชนีไม่และเรามักจะโปรแกรมในระดับที่สูงอยู่แล้ว แต่จะต้องมีความสำคัญมากในบรรดาเครื่อง 0.001GHz และการใช้สิ่งอื่นที่ไม่ใช่*--xหรือ*x++จะมีความหมายที่คุณ ไม่ได้ "รับ" PDP-11 และคุณอาจมีคนมาหาคุณและพูดว่า "คุณรู้ไหมว่า ... " :-) :-)


25
Wikipediaบอกว่า: "ตำนานพื้นบ้าน (เท็จ) ก็คือสถาปัตยกรรมชุดคำสั่งของ PDP-11 มีอิทธิพลต่อการใช้ภาษาการเขียนโปรแกรมภาษา C โหมดการเพิ่มและลดตำแหน่งของ PDP-11 สอดคล้องกับ−−iและi++สร้างใน C. หากiและjทั้งตัวแปรการลงทะเบียนการแสดงออกเช่น*(−−i) = *(j++)สามารถรวบรวมเป็นคำสั่งเครื่องเดียว [... ] Dennis Ritchie ขัดต่อตำนานพื้นบ้านนี้อย่างไม่น่าสงสัย[การพัฒนาภาษา C ]]
fredoverflow

3
Huh (จากลิงค์ที่ให้ไว้ในความคิดเห็นของ FredOverflow): "ผู้คนมักจะเดาว่าพวกเขาถูกสร้างขึ้นเพื่อใช้โหมดที่อยู่ที่เพิ่มขึ้นโดยอัตโนมัติและลดลงโดยอัตโนมัติโดย DEC PDP-11 ซึ่ง C และ Unix เริ่มได้รับความนิยม เป็นไปไม่ได้เนื่องจากไม่มี PDP-11 เมื่อ B ถูกพัฒนาอย่างไรก็ตาม PDP-7 มีเซลล์หน่วยความจำที่เพิ่มขึ้นอัตโนมัติเพียงไม่กี่ตัวโดยมีคุณสมบัติที่การอ้างอิงหน่วยความจำทางอ้อมเพิ่มเซลล์คุณสมบัตินี้อาจเป็นไปได้ แนะนำตัวดำเนินการดังกล่าวให้กับ ธ อมป์สันการวางหลักเกณฑ์ทั่วไปเพื่อทำให้ทั้งคำนำหน้าและ postfix เป็นของเขาเอง "

3
DMR บอกเพียงว่า PDP-11 นั้นไม่ใช่เหตุผลที่เพิ่มเข้าใน C. ฉันก็บอกเช่นกัน สิ่งที่ฉันพูดก็คือมันใช้เพื่อประโยชน์ใน PDP-11 และกลายเป็นรูปแบบการออกแบบที่เป็นที่นิยมด้วยเหตุผลที่แน่นอน หากวิกิพีเดียขัดแย้งกับสิ่งนั้นพวกเขาก็ผิด แต่ฉันไม่ได้อ่านอย่างนั้น มันเป็นประโยคที่ไม่ดีในหน้า W นั้น
DigitalRoss

3
@FredOverflow ฉันคิดว่าคุณเข้าใจผิดว่า "ตำนานพื้นบ้าน" คืออะไร ตำนานคือ C ถูกออกแบบมาเพื่อใช้ประโยชน์จาก 11 ops ไม่ใช่ว่าพวกเขาไม่มีอยู่จริงและไม่ใช่ว่ารูปแบบโค้ดไม่เป็นที่นิยมเพราะทุกคนรู้ว่าพวกเขาแมปกับ 11 ดี ในกรณีที่ไม่ชัดเจน: PDP-11 ใช้สองโหมดเหล่านั้นในฮาร์ดแวร์จริง ๆ สำหรับการเรียนการสอนทุกครั้งในโหมดที่อยู่และมันเป็นเครื่องแรกที่สำคัญ C ที่ทำงานอยู่
DigitalRoss

2
"มันต้องมีความสำคัญกับเครื่อง 0.001GHz มาก" อืมฉันเกลียดที่จะพูดเพราะมันเป็นวันที่ฉัน แต่ฉันมีโมโตโรล่าและ Intel คู่มือสำหรับซีพียูของฉันเพื่อค้นหาขนาดของคำแนะนำและจำนวนรอบที่พวกเขาใช้ การค้นหารหัสที่เล็กที่สุดที่เพิ่มขึ้นเพื่อให้สามารถเพิ่มคุณสมบัติอีกหนึ่งตัวในสพูลเลอร์การพิมพ์และการบันทึกสองรอบหมายความว่าพอร์ตอนุกรมสามารถทันกับโปรโตคอลบางอย่างเช่น MIDI ที่คิดค้นขึ้นใหม่ โดยเฉพาะอย่างยิ่งเมื่อคอมไพเลอร์ปรับปรุง แต่ก็สำคัญที่การรู้ว่าวิธีใดที่มีประสิทธิภาพที่สุดในการเขียนโค้ด
ชายดีบุก

14

คำนำหน้าและ postfix --และ++โอเปอเรเตอร์ได้รับการแนะนำในภาษา B (รุ่นก่อนของ C) โดย Ken Thompson - และไม่พวกเขาไม่ได้รับแรงบันดาลใจจาก PDP-11 ซึ่งไม่มีอยู่ในขณะนั้น

ข้อความจาก"การพัฒนาภาษา C" โดย Dennis Ritchie :

Thompson ไปอีกขั้นด้วยการประดิษฐ์++และ--ผู้ประกอบการที่เพิ่มขึ้นหรือลดลง; คำนำหน้าหรือตำแหน่ง postfix ของพวกเขาเป็นตัวกำหนดว่าการเปลี่ยนแปลงเกิดขึ้นก่อนหรือหลังการสังเกตเห็นค่าของตัวถูกดำเนินการ พวกเขาไม่ได้อยู่ในรุ่นแรกสุดของ B แต่ปรากฏขึ้นระหว่างทาง ผู้คนมักจะเดาว่าพวกเขาถูกสร้างขึ้นเพื่อใช้โหมดที่อยู่เพิ่มขึ้นอัตโนมัติและลดลงอัตโนมัติโดย DEC PDP-11 ซึ่ง C และ Unix ได้รับความนิยมเป็นครั้งแรก สิ่งนี้เป็นไปไม่ได้ในอดีตเนื่องจากไม่มี PDP-11 เมื่อ B ถูกพัฒนาขึ้น อย่างไรก็ตาม PDP-7 มีเซลล์หน่วยความจำ 'เพิ่มขึ้นอัตโนมัติ' สองสามเซลล์โดยมีคุณสมบัติที่หน่วยความจำอ้างอิงทางอ้อมเพิ่มเซลล์ขึ้น คุณลักษณะนี้อาจแนะนำผู้ประกอบการดังกล่าวให้กับ ธ อมป์สัน ลักษณะทั่วไปที่จะทำให้ทั้งคำนำหน้าและ postfix เป็นของเขาเอง อันที่จริง++xx=x+1มีขนาดเล็กกว่า


8
ไม่ฉันไม่เกี่ยวข้องกับ Ken Thompson
Keith Thompson

ขอบคุณสำหรับการอ้างอิงที่น่าสนใจมาก! สิ่งนี้เป็นการยืนยันคำพูดของฉันจาก K&R ดั้งเดิมที่แนะนำเป้าหมายของความเป็นปึกแผ่นมากกว่าการเพิ่มประสิทธิภาพทางเทคนิค ฉันไม่รู้ว่าตัวดำเนินการเหล่านี้มีอยู่แล้วใน B.
Christophe

@BenPen เท่าที่ฉันรู้ว่าไม่มีนโยบายการปิดคำถามหากมีการทำซ้ำในเว็บไซต์ SE ที่แตกต่างกันตราบใดที่คำถามทั้งสองตรงกับเว็บไซต์ที่เกี่ยวข้อง
59

ที่น่าสนใจ ... หนึ่งโปรแกรมเมอร์ไม่ได้ปิดคำถามอย่างแน่นอน
BenPen

@BenPen: คำตอบที่ได้รับการยอมรับสำหรับคำถาม Stack Overflow อ้างอิงแหล่งที่มาเดียวกันกับที่ฉันทำไปแล้ว (แม้ว่าจะไม่ได้ค่อนข้างมาก)
Keith Thompson

6

เหตุผลที่ชัดเจนสำหรับผู้ดำเนินการ postincrement ที่มีอยู่คือเพื่อให้คุณไม่ต้องเขียนนิพจน์เช่น(++x,x-1)หรือ(x+=1,x-1)ทั่วสถานที่หรือแยกงบเล็ก ๆ น้อย ๆ กับผลข้างเคียงที่เข้าใจง่ายออกเป็นหลายงบ นี่คือตัวอย่างบางส่วน:

while (*s) x+=*s++-'0';

if (x) *s++='.';

เมื่อใดก็ตามที่การอ่านหรือเขียนสตริงในทิศทางไปข้างหน้าการโพสต์และไม่ใช่การ preincrement มักเป็นการดำเนินการตามธรรมชาติ ฉันแทบไม่เคยเจอการใช้งานจริงในโลกก่อนการตั้งค่าไว้ล่วงหน้าและการใช้งานที่สำคัญเพียงอย่างเดียวที่ฉันพบสำหรับการตั้งค่าล่วงหน้าคือการแปลงตัวเลขเป็นสตริง (เพราะระบบการเขียนของมนุษย์เขียนตัวเลขไปข้างหลัง)

แก้ไข:จริงๆแล้วมันไม่น่าเกลียดนัก แทนการ(++x,x-1)ที่คุณสามารถในการใช้หลักสูตรหรือ++x-1 (x+=1)-1ยังคงx++สามารถอ่านได้มากขึ้น


คุณต้องระวังเกี่ยวกับนิพจน์เหล่านั้นเนื่องจากคุณกำลังแก้ไขและอ่านตัวแปรระหว่างจุดลำดับสองจุด ลำดับที่นิพจน์เหล่านั้นถูกประเมินไม่รับประกัน

@Snowman: อันไหน? ฉันไม่เห็นปัญหาดังกล่าวในคำตอบของฉัน
..

หากคุณมีสิ่งที่ชอบ(++x,x-1)(การเรียกใช้ฟังก์ชันหรืออาจ?)

@Snowman: นั่นไม่ใช่การเรียกใช้ฟังก์ชัน มันเป็นตัวดำเนินการเครื่องหมายจุลภาค C ซึ่งเป็นจุดลำดับวงเล็บเพื่อควบคุมความสำคัญ ผลลัพธ์จะเหมือนกับx++ในกรณีส่วนใหญ่ (ข้อยกเว้นหนึ่งข้อ: xเป็นประเภทที่ไม่ได้ลงชื่อพร้อมอันดับต่ำกว่าintและค่าเริ่มต้นของxคือค่าสูงสุดของประเภทนั้น)
..

อ๊ะเครื่องหมายคอมม่าที่ยุ่งยาก ... เมื่อเครื่องหมายจุลภาคไม่ใช่เครื่องหมายจุลภาค วงเล็บและความประเสริฐของเครื่องหมายจุลภาคทำให้ฉันหมดแรง ไม่เป็นไร!

4

PDP-11 เสนอการเพิ่มภายหลังและลดการดำเนินการล่วงหน้าในชุดคำสั่ง ตอนนี้ไม่ใช่คำแนะนำ พวกเขาเป็นตัวดัดแปลงคำสั่งที่อนุญาตให้คุณระบุว่าคุณต้องการค่าของการลงทะเบียนก่อนที่จะเพิ่มขึ้นหรือหลังจากนั้นก็ลดลง

นี่คือขั้นตอนการคัดลอกคำในภาษาเครื่อง:

movw (r1)++,(r2)++

ซึ่งย้ายคำจากที่หนึ่งไปอีกที่หนึ่งชี้ไปที่รีจิสเตอร์และรีจิสเตอร์ก็พร้อมที่จะทำอีกครั้ง

เมื่อ C ถูกสร้างขึ้นบนและสำหรับ PDP-11 แนวคิดที่มีประโยชน์มากมายพบว่าพวกเขาเข้าไปใน C. C มีจุดประสงค์เพื่อให้เป็นประโยชน์แทนภาษาแอสเซมเบลอร์ pre-increment และ post-decrement ถูกเพิ่มเข้ามาเพื่อความสมมาตร


นั่นคือตัวดัดแปลงที่ยอดเยี่ยม ... มันทำให้ฉันต้องการเรียนรู้ชุด PDP-11 BTW คุณมีข้อมูลอ้างอิงเกี่ยวกับ "สมมาตรหรือไม่" มันสมเหตุสมผล แต่นี่คือประวัติศาสตร์บางครั้งการทำความเข้าใจไม่ใช่กุญแจ LOL
BenPen

2
หรือที่เรียกว่าโหมดที่อยู่ PDP-11 ให้การโพสต์เพิ่มขึ้นและลดลงล่วงหน้าซึ่งจับคู่กันอย่างดีสำหรับการดำเนินการสแต็ค
Erik Eidt

1
PDP-8 จัดเตรียมการเปลี่ยนทิศทางหน่วยความจำหลังการเพิ่ม แต่ไม่มีการดำเนินการลดลงที่สอดคล้องกัน ด้วยหน่วยความจำแกนแม่เหล็กการอ่านคำในหน่วยความจำจะลบออก (!) ดังนั้นโปรเซสเซอร์จึงใช้ฟังก์ชั่นเขียนกลับเพื่อเรียกคืนคำที่เพิ่งอ่าน การใช้การเพิ่มขึ้นก่อนที่จะเขียนกลับมาค่อนข้างเป็นธรรมชาติและการย้ายบล็อกที่มีประสิทธิภาพมากขึ้นก็เป็นไปได้
Erik Eidt

3
ขออภัย PDP-11 ไม่ได้เป็นแรงบันดาลใจให้ผู้ให้บริการเหล่านี้ มันยังไม่มีอยู่เมื่อ Ken Thompson คิดค้นพวกเขา ดูคำตอบของฉัน
Keith Thompson

3

ฉันสงสัยว่ามันจำเป็นจริงๆ เท่าที่ฉันรู้มันไม่ได้รวบรวมอะไรที่กะทัดรัดในแพลตฟอร์มส่วนใหญ่มากกว่าการใช้การเพิ่มล่วงหน้าตามที่คุณทำในลูป มันเป็นเพียงแค่ตอนที่มันถูกสร้างขึ้นความตึงของรหัสนั้นสำคัญกว่าความคมชัดของรหัส

ไม่ได้หมายความว่าความชัดเจนของโค้ดนั้นไม่สำคัญ (หรือไม่สำคัญ) แต่เมื่อคุณพิมพ์ด้วยโมเด็มความเร็วต่ำ (สิ่งที่คุณวัดค่าด้วยความเร็วต่ำช้า) ซึ่งการกดแป้นทุกครั้งต้องทำให้ เมนเฟรมแล้วสะท้อนกลับทีละหนึ่งไบต์โดยใช้บิตเดียวเป็นการตรวจสอบพาริตี้คุณไม่ต้องการพิมพ์มากนัก

นี่เป็นเหมือน & & | ผู้ประกอบการที่มีความสำคัญต่ำกว่า ==

มันได้รับการออกแบบด้วยความตั้งใจที่ดีที่สุด (รุ่นที่ไม่ลัดวงจรของ && และ ||) แต่ตอนนี้มันทำให้ผู้เขียนโปรแกรมสับสนทุกวันและมันอาจจะไม่เปลี่ยนแปลงเลย

อย่างไรก็ตามนี่เป็นเพียงคำตอบที่ฉันคิดว่าไม่มีคำตอบที่ดีสำหรับคำถามของคุณ แต่ฉันอาจได้รับการพิสูจน์ว่าผิดโดย coder กูรูมากกว่าฉัน

--EDIT--

ฉันควรทราบว่าฉันพบว่าทั้งสองมีประโยชน์อย่างเหลือเชื่อฉันแค่ชี้ให้เห็นว่ามันจะไม่เปลี่ยนแปลงไม่ว่าจะมีใครชอบหรือไม่


นี่ไม่ใช่เรื่องจริงจากระยะไกล ไม่มีจุดใดที่ "ความบิดเบี้ยวของรหัส" สำคัญกว่าความคมชัด
Cody Grey

ฉันจะเถียงว่ามันเป็นจุดสนใจมากขึ้น คุณกำลังค่อนข้างขวา แต่ก็แน่นอนไม่เคยมีมากขึ้นที่สำคัญกว่าความคมชัดของรหัส ... เพื่อคนส่วนใหญ่

6
ดีคำนิยามของ "สั้นที่"เป็น "อย่างราบรื่นสง่างาม: ขัด" หรือ "ใช้คำไม่กี่คำ: ไร้ superfluity" ซึ่งทั้งสองมักจะมีสิ่งที่ดีเมื่อเขียนโค้ด "Terse" ไม่ได้แปลว่า "คลุมเครืออ่านยากและสับสน" ตามที่หลายคนคิด
James McNellis

@ James: ในขณะที่คุณถูกต้องฉันคิดว่าคนส่วนใหญ่หมายถึงคำจำกัดความที่สองของ "terse" เมื่อใช้ในการเขียนโปรแกรมบริบท: "ใช้คำไม่กี่คำ; ไร้ไร้ประสิทธิภาพ" ภายใต้คำจำกัดความนั้นมันง่ายกว่าที่จะจินตนาการถึงสถานการณ์ที่มีการแลกเปลี่ยนระหว่างความกะทัดรัดและความหมายของโค้ดบางส่วน เห็นได้ชัดว่าสิ่งที่ถูกต้องที่ต้องทำเมื่อเขียนโค้ดนั้นเป็นสิ่งเดียวกับเมื่อพูด: ทำสิ่งที่สั้นที่สุดเท่าที่จำเป็น แต่ไม่สั้นลง การประเมินค่าความคลาดเคลื่อนในเรื่องของนิพจน์อาจนำไปสู่การมองดูที่สับสน แต่ก็ไม่ควรแน่นอน
Cody Gray

1
ย้อนกลับไป 40 ปีและจินตนาการว่าคุณต้องติดตั้งโปรแกรมของคุณบนดรัมนั้นซึ่งจะมีตัวอักษรประมาณ 1,000 ตัวเท่านั้นหรือการเขียนคอมไพเลอร์สามารถทำงานได้กับแรม 4 พันไบท์เท่านั้น มีหลายครั้งที่ความตึงเครียดเมื่อเทียบกับความคมชัดไม่ใช่ปัญหา คุณจะต้องเข้าใจอย่างถ่องแท้ไม่มีคอมพิวเตอร์อยู่บนโลกใบนี้ที่สามารถเก็บรันหรือคอมไพล์โปรแกรมที่ไม่ใช่ตัวย่อของคุณ
nos

3

ฉันชอบ aperator postfix เมื่อต้องรับมือกับพอยน์เตอร์ (ไม่ว่าฉันจะพูดถึงมันหรือไม่ก็ตาม) เพราะ

p++

อ่านเป็นธรรมชาติมากขึ้นว่า "ย้ายไปยังจุดต่อไป" มากกว่าที่เทียบเท่า

p += 1

ซึ่งแน่นอนว่าจะต้องสร้างความสับสนให้กับผู้เริ่มต้นในครั้งแรกที่เห็นมันใช้กับตัวชี้โดยที่ sizeof (* p)! = 1

คุณแน่ใจหรือไม่ว่าคุณระบุปัญหาความสับสนอย่างถูกต้อง ไม่ใช่สิ่งที่ทำให้ผู้เริ่มต้นสับสนว่าผู้ประกอบการ postfix ++ มีลำดับความสำคัญสูงกว่าผู้ดำเนินการ dereference * เพื่อให้

*p++

แยกวิเคราะห์เป็น

*(p++)

และไม่

(*p)++

บางคนอาจคาดหวัง

(คุณคิดว่าไม่ถูกต้องหรือไม่ดูการอ่านประกาศ C )


2

ในบรรดาองค์ประกอบที่ละเอียดอ่อนของการเขียนโปรแกรมที่ดีคือการโลคัลไลซ์ชันและเรียบง่าย :

  • วางตัวแปรในขอบเขตการใช้งานที่น้อยที่สุด
  • ใช้ const เมื่อไม่จำเป็นต้องเข้าถึงเพื่อเขียน
  • เป็นต้น

ในจิตวิญญาณเดียวกันx++สามารถมองเห็นได้ว่าเป็นวิธีหนึ่งในการแปลข้อมูลอ้างอิงถึงมูลค่าปัจจุบันของxในขณะที่ระบุว่าคุณ - อย่างน้อยตอนนี้เสร็จสิ้นด้วยค่านั้นทันทีและต้องการย้ายไปยังถัดไป (ใช้ได้ไม่ว่าxจะเป็นintหรือ ตัวชี้หรือตัววนซ้ำ) ด้วยจินตนาการเล็กน้อยคุณสามารถเปรียบเทียบสิ่งนี้กับการปล่อยให้ค่า / ตำแหน่งเดิมx"หลุดออกจากขอบเขต" ทันทีหลังจากที่ไม่ต้องการอีกต่อไปและย้ายไปยังค่าใหม่ จุดที่แม่นยำที่การเปลี่ยนแปลงนั้นเป็นไปได้จะถูกเน้นโดย postfix++จุดที่แม่นยำที่การเปลี่ยนแปลงที่เป็นไปได้ที่จะถูกเน้นด้วยกับ Postfixความหมายที่ว่านี่อาจเป็นการใช้งานครั้งสุดท้ายของ "เก่า" xเป็นข้อมูลเชิงลึกที่มีค่าเกี่ยวกับอัลกอริทึมช่วยโปรแกรมเมอร์ขณะที่สแกนผ่านโค้ดที่อยู่รอบ ๆ แน่นอน postfix++ อาจทำให้โปรแกรมเมอร์มองหาการใช้ค่าใหม่ซึ่งอาจหรืออาจจะไม่ดีขึ้นอยู่กับว่าจำเป็นต้องใช้ค่าใหม่จริงหรือไม่ดังนั้นจึงเป็นแง่มุมของ "ศิลปะ" หรือ "งานฝีมือ" ของการเขียนโปรแกรมเพื่อกำหนดสิ่งที่มากกว่า มีประโยชน์ในสถานการณ์

ในขณะที่ผู้เริ่มต้นหลายคนอาจสับสนกับคุณสมบัติ แต่ก็คุ้มค่าที่จะเทียบกับผลประโยชน์ระยะยาว: ผู้เริ่มต้นไม่ต้องอยู่กับผู้เริ่มต้นเป็นเวลานาน


2

ว้าวคำตอบมากมายไม่ใช่ - ค่อนข้างตรงประเด็น (ถ้าฉันกล้ามาก) และโปรดยกโทษให้ฉันถ้าฉันชี้ให้เห็นอย่างชัดเจนโดยเฉพาะอย่างยิ่งในความคิดเห็นของคุณที่จะไม่ชี้ให้เห็นความหมาย แต่ชัดเจน (จากมุมมองของ Stroustrup ฉันคิดว่า) ยังไม่ได้โพสต์! :)

Postfix x++สร้างแบบชั่วคราวที่ส่งผ่าน 'upwards' ในนิพจน์ในขณะที่ตัวแปรxเพิ่มขึ้นในภายหลัง

คำนำหน้า++xไม่ได้สร้างวัตถุชั่วคราว แต่เพิ่ม 'x' และส่งผ่านผลลัพธ์ไปยังนิพจน์

ค่าคือความสะดวกสบายสำหรับผู้ที่รู้ว่าผู้ประกอบการ

ตัวอย่างเช่น:

int x = 1;
foo(x++); // == foo(1)
// x == 2: true

x = 1;
foo(++x); // == foo(2)
// x == 2: true

แน่นอนผลลัพธ์ของตัวอย่างนี้สามารถสร้างจากโค้ดอื่น ๆ ที่เทียบเท่ากัน (และอาจจะเอียงน้อยกว่า)

เหตุใดเราจึงมีผู้ให้บริการ postfix ฉันเดาว่าเพราะมันเป็นสำนวนที่ยังคงอยู่แม้จะเกิดความสับสนอย่างเห็นได้ชัดก็ตาม มันเป็นสิ่งก่อสร้างดั้งเดิมที่ครั้งหนึ่งเคยถูกมองว่ามีคุณค่าแม้ว่าฉันจะไม่แน่ใจว่าการรับรู้คุณค่านั้นมีความสำคัญต่อประสิทธิภาพในการทำงานมากนัก ความสะดวกสบายนั้นไม่ได้สูญหายไป แต่ฉันคิดว่าการเพิ่มความสามารถในการอ่านได้เพิ่มขึ้นส่งผลให้มีการซักถามถึงจุดประสงค์ของผู้ปฏิบัติงาน

เราต้องการผู้ประกอบการ postfix อีกต่อไปหรือไม่ น่าจะไม่ ผลที่ได้คือทำให้เกิดความสับสนและสร้างอุปสรรคต่อความเข้าใจ ผู้เขียนโค้ดที่ดีบางคนจะรู้ทันทีว่าจะพบว่ามีประโยชน์ที่ไหนในสถานที่ที่มีความงาม "PERL-esque" ที่แปลกประหลาด ค่าใช้จ่ายของความงามนั้นสามารถอ่านได้

ฉันยอมรับว่ารหัสที่ชัดเจนมีประโยชน์มากกว่าความเข้มงวดในการอ่านเข้าใจและบำรุงรักษา นักออกแบบและผู้จัดการที่ดีต้องการสิ่งนั้น

อย่างไรก็ตามมีความงามบางอย่างที่โปรแกรมเมอร์บางคนจำได้ว่าสนับสนุนให้พวกเขาสร้างโค้ดด้วยสิ่งต่าง ๆ เพื่อความเรียบง่ายสวยงาม - เช่นโอเปอเรเตอร์ postfix - ซึ่งโค้ดที่พวกเขาไม่เคยนึกถึงมาก่อน - หรือพบว่ามีการกระตุ้นทางสติปัญญา มีบางอย่างที่ทำให้มันสวยงามมากขึ้นหากไม่ต้องการมากขึ้นแม้จะมีสาระสำคัญ

ในคำอื่น ๆ บางคนพบว่าwhile (*dst++ = *src++);เป็นเพียงวิธีการแก้ปัญหาที่สวยงามมากขึ้นบางสิ่งที่ทำให้คุณหายใจด้วยความเรียบง่ายเช่นเดียวกับที่มันเป็นแปรงบนผืนผ้าใบ ที่คุณถูกบังคับให้เข้าใจภาษาเพื่อชื่นชมความงามเท่านั้นที่เพิ่มความงดงาม


3
+1 "บางคนพบในขณะที่ (* dst ++ = * src ++) เพื่อเป็นทางออกที่สวยงามยิ่งขึ้น" อย่างแน่นอน. ผู้ที่ไม่เข้าใจภาษาแอสเซมบลีไม่เข้าใจความสวยงามของ C ได้อย่างแท้จริง แต่คำสั่งรหัสเฉพาะนั้นเป็นดาวที่เปล่งประกาย
ชายดีบุก

"เราต้องการโอเปอเรเตอร์ postfix อีกต่อไปใช่ไหม?" - ฉันอดคิดถึงเครื่องจักรทัวริงที่นี่ไม่ได้ เราเคยต้องการตัวแปรอัตโนมัติforคำสั่ง heck แม้while(เรามีgotoหลังจากทั้งหมด)?

@Bernd: ฮ่า! ลองนึกภาพการปิด! ปิด! อื้อฉาว! lol
Brian M. Hunt

ปิด! ไร้สาระแค่ไหน เพียงแค่ให้ฉันเทป! อย่างจริงจังสิ่งที่ฉันหมายถึงคือฉันไม่คิดว่า / ต้องการ / คุณลักษณะควรเป็นเกณฑ์การตัดสินใจหลัก (เว้นแต่คุณต้องการออกแบบพูดพูดชัดแจ้ง) ฉันใช้ IME (ไม่จำเป็นต้องใช้ ) ตัวดำเนินการ postfix โดยเฉพาะและแทบจะไม่ต้องการคำนำหน้าเลย

2

ลองดูเหตุผลต้นฉบับของ Kernighan & Ritchie (ต้นฉบับ K&R หน้า 42 และ 43):

ลักษณะที่ผิดปกติคือ ++ และ - อาจใช้เป็นคำนำหน้าหรือเป็นคำนำหน้า (... ) ในบริบทที่ไม่ต้องการค่า (.. ) เลือกคำนำหน้าหรือ postfix ตามรสนิยม แต่ htere เป็นสถานการณ์ที่หนึ่งหรืออื่น ๆ ถูกเรียกโดยเฉพาะสำหรับ

ข้อความยังคงดำเนินต่อไปด้วยตัวอย่างบางส่วนที่ใช้การเพิ่มขึ้นภายในดัชนีโดยมีเป้าหมายชัดเจนในการเขียน " กระชับยิ่งขึ้นโค้ด " " ดังนั้นเหตุผลที่อยู่เบื้องหลังผู้ประกอบการเหล่านี้คือความสะดวกสบายของรหัสกะทัดรัดมากขึ้น

สามตัวอย่างที่กำหนด ( squeeze(), getline()และstrcat() ) ใช้ postfix เฉพาะภายในแสดงออกโดยใช้การจัดทำดัชนี ผู้เขียนเปรียบเทียบรหัสกับรุ่นที่ยาวกว่าซึ่งไม่ได้ใช้การเพิ่มทีละฝัง นี่เป็นการยืนยันว่าโฟกัสอยู่ที่ความกะทัดรัด

ไฮไลต์ K&R ในหน้า 102 การใช้โอเปอเรเตอร์เหล่านี้ร่วมกับตัวชี้การกระจายสัญญาณ (เช่น*--pและ*p-- ) ไม่มีตัวอย่างเพิ่มเติมอีกแล้ว แต่อีกครั้งพวกเขาทำให้ชัดเจนว่าประโยชน์คือความเป็นปึกแผ่น

คำนำหน้าเป็นตัวอย่างที่ใช้บ่อยมากเมื่อลดค่าดัชนีหรือตัวชี้จ้องมองจากปลาย

 int i=0; 
 while (i<10) 
     doit (i++);  // calls function for 0 to 9  
                  // i is 10 at this stage
 while (--i >=0) 
     doit (i);    // calls function from 9 to 0 

1

ผมจะไม่เห็นด้วยกับสมมติฐานที่ว่า++p, p++เป็นอย่างใดยากที่จะอ่านหรือไม่ชัดเจน หนึ่งหมายถึง "increment p แล้วอ่าน p" อีกวิธีหนึ่งหมายถึง "read p และเพิ่มขึ้น p" ในทั้งสองกรณีตัวดำเนินการในรหัสนั้นตรงกับที่อยู่ในคำอธิบายของรหัสดังนั้นถ้าคุณรู้ว่าสิ่งที่++หมายถึงคุณรู้ว่ารหัสผลลัพธ์

คุณสามารถสร้างรหัสที่สับสนโดยใช้ไวยากรณ์ใด ๆแต่ฉันไม่เห็นกรณีที่นี่p++/ ++pเป็นobfuscatory โดยเนื้อแท้


1

นี่คือจาก POV ของวิศวกรไฟฟ้า:

มีโปรเซสเซอร์จำนวนมากที่มีตัวดำเนินการหลังการเพิ่มและการลดลงล่วงหน้าเพื่อวัตถุประสงค์ในการรักษาสแต็กล่าสุดเข้าก่อนออก (LIFO)

มันอาจจะเป็นเช่น:

 float stack[4096];
 int stack_pointer = 0;

 ... 

 #define push_stack(arg) stack[stack_pointer++] = arg;
 #define pop_stack(arg) arg = stack[--stack_pointer];

 ...

ฉันไม่รู้, แต่นั่นคือเหตุผลที่ฉันคาดหวังว่าจะเห็นทั้งตัวดำเนินการเพิ่มคำนำหน้าและ postfix


1

เพื่อเน้นย้ำถึงจุดแข็งของ Christophe ฉันต้องการแสดงรหัสบางส่วนจาก V6 นี่เป็นส่วนหนึ่งของคอมไพเลอร์ C ดั้งเดิมจากhttp://minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/source/c/c00.c :

/*
 * Look up the identifier in symbuf in the symbol table.
 * If it hashes to the same spot as a keyword, try the keyword table
 * first.  An initial "." is ignored in the hash.
 * Return is a ptr to the symbol table entry.
 */
lookup()
{
    int ihash;
    register struct hshtab *rp;
    register char *sp, *np;

    ihash = 0;
    sp = symbuf;
    if (*sp=='.')
        sp++;
    while (sp<symbuf+ncps)
        ihash =+ *sp++;
    rp = &hshtab[ihash%hshsiz];
    if (rp->hflag&FKEYW)
        if (findkw())
            return(KEYW);
    while (*(np = rp->name)) {
        for (sp=symbuf; sp<symbuf+ncps;)
            if (*np++ != *sp++)
                goto no;
        csym = rp;
        return(NAME);
    no:
        if (++rp >= &hshtab[hshsiz])
            rp = hshtab;
    }
    if(++hshused >= hshsiz) {
        error("Symbol table overflow");
        exit(1);
    }
    rp->hclass = 0;
    rp->htype = 0;
    rp->hoffset = 0;
    rp->dimp = 0;
    rp->hflag =| xdflg;
    sp = symbuf;
    for (np=rp->name; sp<symbuf+ncps;)
        *np++ = *sp++;
    csym = rp;
    return(NAME);
}

นี่คือรหัสที่ถูกส่งไปใน samizdat เพื่อการศึกษาในรูปแบบที่ดี แต่เราจะไม่เขียนมันแบบนี้ในวันนี้ ดูว่ามีผลข้างเคียงมากมายที่บรรจุลงในifและwhileเงื่อนไขและในทางกลับกันforลูปทั้งสองไม่มีการแสดงออกที่เพิ่มขึ้นเพราะมันทำในร่างกายของลูป ดูว่าบล็อกถูกห่อด้วยเครื่องมือจัดฟันอย่างไรเมื่อจำเป็นจริงๆ

ส่วนนี้เป็นคู่มืออย่างแน่นอนไมโครเพิ่มประสิทธิภาพของการจัดเรียงที่เราคาดว่าคอมไพเลอร์ที่จะทำสำหรับเราในวันนี้ แต่ฉันยังอยากจะหยิบยกสมมติฐานที่ว่าเมื่ออินเตอร์เฟซของคุณทั้งหมดไปยังเครื่องคอมพิวเตอร์เป็น TTY แก้ว 80x25 เดียวที่คุณต้องการรหัสของคุณ มีความหนาแน่นมากที่สุดเท่าที่จะเป็นไปได้เพื่อให้คุณสามารถดูได้มากขึ้นในเวลาเดียวกัน

(การใช้บัฟเฟอร์สากลสำหรับทุกสิ่งน่าจะเป็นอาการเมาค้างจากการตัดฟันเป็นภาษาแอสเซมบลี)


จัดการด้วยความระมัดระวัง: "ihash = + * sp ++;" ในบางจุด C ไม่เพียง แต่มีเครื่องหมาย + = แต่ยังมีเครื่องหมาย + อีกด้วย วันนี้ = + เป็นผู้ดำเนินการที่ได้รับมอบหมายตามด้วยเครื่องหมายบวกซึ่งไม่ได้ทำอะไรเลยดังนั้นจึงเท่ากับ "ihash = * sp; sp + = 1;"
gnasher729

@ gnasher729 ใช่และต่อมาก็มีrp->hflag =| xdflgซึ่งฉันเชื่อว่าจะเป็นข้อผิดพลาดทางไวยากรณ์ในคอมไพเลอร์ที่ทันสมัย "ณ จุดหนึ่ง" เป็น V6 อย่างแม่นยำในขณะที่มันเกิดขึ้น; การเปลี่ยนแปลงเพื่อ+=ก่อให้เกิด happend ใน V7 (คอมไพเลอร์ V6 ยอมรับเฉพาะ=+ถ้าฉันอ่านรหัสนี้อย่างถูกต้อง - ดูสัญลักษณ์ () ในไฟล์เดียวกัน)
zwol

-1

บางทีคุณควรคิดถึงเครื่องสำอางด้วย

while( i++ )

เนื้อหา "ดูดีกว่า" กว่า

while( i+=1 )

ด้วยเหตุผลบางอย่างผู้ประกอบการโพสต์เพิ่มขึ้นดูน่าสนใจมาก มันสั้นหวานและมันเพิ่มทุกอย่างด้วย 1 เปรียบเทียบกับคำนำหน้า:

while( ++i )

"ดูย้อนหลัง" ใช่ไหม คุณไม่เคยเห็นเครื่องหมายบวกเป็นครั้งแรกในวิชาคณิตศาสตร์ยกเว้นเมื่อใครบางคนกำลังงี่เง่าพร้อมระบุสิ่งที่เป็นบวก ( +0หรืออะไรทำนองนั้น) เราเคยเห็นสิ่งที่เป็นวัตถุ + บางสิ่งบางอย่าง

มันเป็นเรื่องเกี่ยวกับการให้คะแนนหรือไม่? A, A +, A ++? ฉันสามารถบอกคุณได้ว่าฉันถูกชีสสวยในตอนแรกที่คน Python ลบออกoperator++จากภาษาของพวกเขา!


1
ตัวอย่างของคุณไม่ได้ทำสิ่งเดียวกัน i++ส่งกลับค่าเดิมของiและi+=1และ++iส่งกลับค่าเดิมของiแถม 1 เมื่อคุณกำลังใช้ค่าผลตอบแทนสำหรับการควบคุมการไหลเรื่องนี้
David Thornley

ใช่คุณพูดถูก. แต่ฉันดูที่การอ่านที่นี่เท่านั้น
bobobobo

-2

นับถอยหลังไป 9 ถึง 0 รวม:

for (unsigned int i=10; i-- > 0;)  {
    cout << i << " ";
}

หรือเทียบเท่าขณะลูป


1
แล้วไงfor (unsigned i = 9; i <= 9; --i)ล่ะ
fredoverflow
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.