“ สำหรับ (;;)” เร็วกว่า“ ขณะ (TRUE)” หรือไม่ ถ้าไม่ทำไมผู้คนถึงใช้มัน?


164
for (;;) {
    //Something to be done repeatedly
}

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

ฉันเดาว่า (เช่นเดียวกับเหตุผลที่โปรแกรมเมอร์หลายคนหันไปใช้รหัสลับ) นี่เป็นอัตรากำไรขั้นต้นที่น้อยกว่าหรือไม่

ทำไมและมันคุ้มค่าจริงหรือ ถ้าเป็นเช่นนั้นทำไมไม่กำหนดเพียงวิธีนี้:

#define while(true) for(;;)

ดูเพิ่มเติม: อันไหนเร็วกว่าในขณะที่ (1) หรือขณะที่ (2)?


51
อะไรคือTRUE???
AnT

20
@Steven Sudit: TRUEC เกี่ยวข้องกับอะไร? มาโครมาตรฐานสำหรับผลลัพธ์บูลีนที่แท้จริงใน C99 ยังคงtrueอยู่ ในกรณีที่การไม่TRUEมาจากไหน?
ANT

31
มาโครนั้นใช้งานไม่#define EVER ;;ได้มีการใช้งานใน IOCCC .. :)

18
มาโครนั้นไม่ใช่การ#define while(TRUE)ประกาศมาโครที่รับอาร์กิวเมนต์หนึ่งTRUEที่ไม่เคยใช้มาก่อนดังนั้นให้เปลี่ยนทุก ๆ ขณะที่วนรอบในโปรแกรมของคุณเป็นวงวนไม่สิ้นสุด?
AshleysBrain

9
@Steven Sudit: ไม่ไม่มี "มาโครมาตรฐานใน VS 6.0" แมโครTRUEมาจากไฟล์ส่วนหัวที่เชื่อมโยงกับ Windows API ไม่เกี่ยวข้องกับ VS 6.0 แต่อย่างใด และอย่างที่ฉันพูดไปก่อนหน้านี้มันไม่มีส่วนเกี่ยวข้องกับ C หรือ C ++ ใน C ++ อักษร "จริง" เป็นเพียงtrue(ใน VS 6.0 เช่นกัน) ใน C89 / 90 ไม่มีสิ่งดังกล่าวที่ทั้งหมดและใน C99 trueมันเป็นแมโคร สิ่งนี้ใช้กับคอมไพเลอร์ C / C ++ ทั้งหมด
An

คำตอบ:


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

227
การเพิ่มประสิทธิภาพการวนซ้ำแบบไม่สิ้นสุดทำให้เกิดศักยภาพในการเร่งความเร็วแบบไม่สิ้นสุด สิ่งที่ดีที่เราไม่ได้เขียนโปรแกรมด้วยสัญชาตญาณแล้ว :-)
Steven Sudit

5
ฉันคิดว่าคุณพูดถูก ฉันคิดว่าฉันถูกจับในการอภิปราย "ศาสนา" เกี่ยวกับสิ่งเล็ก ๆ น้อย ๆ ขอบคุณที่เขย่ามโนธรรมของฉันหลวม : D
Chris Cooper

6
@Steven LOL ที่น่าสนใจ แต่ให้พิจารณาว่าสถานการณ์เดียวที่คุณมีศักยภาพในการเร่งความเร็วที่ไม่สิ้นสุดคือเมื่อลูปไม่เคยหยุดและทำงานได้อย่างไม่สิ้นสุดซึ่งน่าจะเป็นข้อผิดพลาดหรือถ้าตั้งใจจะเป็น การรอที่ไม่มีที่สิ้นสุดก่อนที่จะถึงศักยภาพนั้น
AaronLS

7
@ Chris ในการเขียนโปรแกรมเช่นเดียวกับในชีวิตการอภิปรายทางศาสนานั้นคุ้มค่ากับเวลาของคุณสำหรับสิ่งที่สำคัญจริงๆ นี่ไม่ใช่สิ่งเหล่านั้นอย่างใดอย่างหนึ่ง อย่างที่คุณเห็นทุกคนมีวิธีการเขียนวนสัตว์เลี้ยงที่ไม่รู้จักจบ เลือกสิ่งที่ทำให้คุณมีความสุขที่สุดสำหรับสิ่งเล็ก ๆ น้อย ๆ จากนั้นเรียกใช้โปรแกรมสร้างโปรไฟล์บนโค้ดที่สำคัญ :)
Ben Zotto

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

176

ฉันชอบfor(;;)ด้วยเหตุผลสองประการ

หนึ่งคือคอมไพเลอร์บางคนสร้างคำเตือนwhile(true)(เช่น "สภาพลูปเป็นค่าคงที่") การหลีกเลี่ยงคำเตือนเป็นสิ่งที่ควรทำ

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

ในขณะที่มีwhile(true)ดีสิ่งที่มีจริงจะทำอย่างไรกับอะไร? ฉันไม่สนใจที่จะวนซ้ำจนกว่าความจริงจะกลายเป็นเท็จซึ่งเป็นสิ่งที่แบบฟอร์มนี้พูดอย่างแท้จริง (วนซ้ำในขณะที่ความจริงเป็นจริง) ฉันแค่ต้องการวนซ้ำ

และไม่ไม่มีความแตกต่างด้านประสิทธิภาพอย่างแน่นอน


73
+1 สำหรับหลีกเลี่ยงคำเตือน แต่สำหรับความชัดเจนฉันพบว่าชัดเจนกว่าในบริบทนี้ ฉันเดาว่าแง่มุมนั้นลดลงตามความชอบส่วนตัว
ทิม

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

7
ความคิดเห็นของ jalf เกี่ยวกับการใช้คำว่าสำนวนเป็นคำตอบจริงๆที่นี่ มันใช้กันทั่วไปสำหรับ "infinite loop" เพียงเพราะมันเป็นวิธีที่ใช้กันทั่วไปในการเขียน "infinite loop" ใน C. ไม่จำเป็นต้องมีเหตุผลที่ดีสำหรับสำนวน - มันเป็นเพียงแค่การเสริมแรงด้วยตนเอง
caf

7
@ Steve: ผมไม่เห็นเหตุผลที่ฉันเคยfor(;condition;)ใช้ นั่นคือสิ่งที่ห่วงในขณะที่เป็นสำหรับ แต่เหมือนที่ฉันพูดด้วยลูปไม่ จำกัด ฉันไม่ต้องการให้คอมไพเลอร์เปรียบเทียบเงื่อนไขใด ๆ อย่างไร้เดียงสากับwhileวงก็ต้องการมีการทดสอบtrueทุกซ้ำ (ชัดไม่ได้คอมไพเลอร์พึงจะทำอย่างนั้น แต่มันก็เป็นหลักการที่ว่ารบกวนจิตใจผม. จะนัดฉันเป็น overspecifying รหัสของคุณ) ในขณะที่มีfor(;;)คุณมีอักษรบอกว่า "ไม่มีเงื่อนไขในการทดสอบเพียงแค่วนซ้ำ" ฉันคิดว่ามันใกล้เคียงกับจินตภาพของคุณมากที่สุดloop {...}
jalf

32
คอมไพเลอร์ของคุณแย่ถ้าwhile(true)ให้คำเตือน
อัลเบิร์ต

56

ส่วนตัวฉันใช้for (;;)เพราะไม่มีตัวเลขใด ๆ มันเป็นเพียงคำหลัก ฉันชอบมันwhile (true), while (1), while (42), while (!0)ฯลฯ เป็นต้น


38
0, 1 และอินฟินิตี้เป็นตัวเลขเวทย์มนตร์ที่ยอมรับได้โดยการขยาย 0 และ 1 ไปเป็นเท็จและจริงไม่ใช่การสูญเสีย trueไม่มีหมายเลขเวทมนต์มากไปกว่าforคำหลักเวทย์มนตร์หรือที่for(;;)ใช้อินฟินิตี้เวทมนตร์โดยนัย ( while (42)เป็นสิ่งที่น่ารังเกียจจริงๆ)

38
แทนเจนต์: หนึ่งในอาจารย์ CS ของฉันกล่าวว่า "มีเพียงสามตัวเลขในการเขียนโปรแกรม: 0, 1 และ n. สิ่งอื่นใดเรียกว่าหมายเลขวิเศษ"
Ben Zotto

21
ในขณะที่ (42) เป็นสิ่งที่เจ๋งที่สุดไม่สร้างผลลัพธ์ที่แตกต่างเมื่อเทียบกับ (1) หรือในขณะที่ (จริง) หรือขณะที่ (! 0) และมีความหมายทางปรัชญา ฉันคิดว่าfor(;;)จะถูกแจงเร็วกว่าคนอื่น ๆ อยู่ดี
ShinTakezou

2
@ShinTakezou ดีกว่ามาก#define LIFE 42 while (LIFE):)
mr5

1
ดีwhile(true)ไม่มีหมายเลขใด ๆ เกินไป และสำหรับ (;;) ไม่ใช่คำหลัก
RiaD

49

เพราะเดนนิสริตชี่

  • ฉันเริ่มใช้for (;;)เพราะนั่นคือวิธีที่ Dennis Ritchie ทำใน K&R และเมื่อเรียนรู้ภาษาใหม่ฉันพยายามเลียนแบบพวกที่ฉลาด

  • นี่คือสำนวน C / C ++ น่าจะดีกว่าในระยะยาวหากคุณคุ้นเคยกับการทำสิ่งต่างๆในพื้นที่ C / C ++

  • คุณ#defineจะไม่ทำงานเนื่องจากสิ่งที่ # define'd ต้องดูเหมือนกับตัวระบุ C

  • คอมไพเลอร์สมัยใหม่ทั้งหมดจะสร้างรหัสเดียวกันสำหรับการสร้างทั้งสอง


10
ใช่นี่คือวิธีที่คุณรู้ว่ามีคนเรียนรู้ C จาก K&R วิธีที่ควรเรียนรู้ เมื่อใดก็ตามที่ฉันเห็นwhile(TRUE)ฉันสงสัยว่าโปรแกรมเมอร์คือ C มือใหม่หรือเรียนรู้ C จากหนังสือ For Dummies
Kristopher Johnson

13
ฉันได้ยินว่ามือใหม่เหล่านั้นใช้สไตล์นิยามฟังก์ชั่น new Fangledด้วย
Justin

46

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

หากคุณสงสัยนี่คือสิ่งที่ gcc 4.4.1 มอบให้ฉันสำหรับ x86 ทั้งคู่ใช้คำสั่งx86 JMP

void while_infinite()
{
    while(1)
    {
    puts("while");
    }
}

void for_infinite()
{
    for(;;)
    {
    puts("for");
    }
}

รวบรวมเป็น (บางส่วน):

.LC0:
.string "while"
.text
.globl while_infinite
    .type   while_infinite, @function
while_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L2:
    movl    $.LC0, (%esp)
    call    puts
    jmp .L2
    .size   while_infinite, .-while_infinite
    .section    .rodata
.LC1:
    .string "for"
    .text
.globl for_infinite
    .type   for_infinite, @function
for_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L5:
    movl    $.LC1, (%esp)
    call    puts
    jmp .L5
    .size   for_infinite, .-for_infinite

ฉันสงสัยว่ามันเร็วกว่าแม้ในโหมดแก้ไขข้อบกพร่อง
Steven Sudit

106
for_infiniteเร็วกว่า; 2 putsตัวละครน้อยลงไป
Dave Jarvis

43

ฉันชอบfor (;;)เพราะมันสอดคล้องกันมากที่สุดในภาษา C ที่แตกต่างกัน

ใน C ++ while (true)นั้นใช้ได้ แต่ใน C คุณขึ้นอยู่กับส่วนหัวที่จะกำหนดtrueแต่TRUEเป็นมาโครที่ใช้กันทั่วไป ถ้าคุณใช้while (1)มันถูกต้องใน C และ C ++ และ JavaScript แต่ไม่ Java หรือ C # ซึ่งต้องห่วงสภาพที่จะเป็นแบบบูลเช่นหรือwhile (true) while (1 == 1)ใน PHP คำหลักกรณีตาย TRUEแต่ภาษาที่ชอบเป็นทุน

อย่างไรก็ตามfor (;;)ถูกต้องเสมอในทุกภาษาเหล่านั้น


9
ขอบคุณสำหรับคำตอบ! ฉันคิดว่านี่เป็นคำตอบแรกที่แสดงให้เห็นถึงเป้าหมายที่for (;;)ดีกว่า
Chris Cooper

8
ฉันไม่คิดว่าฉันจะต้องเขียนโค้ดที่ถูกต้องใน C, C ++, JavaScript, Java และ C # พวกเขาเป็นภาษาที่แตกต่างกัน
Keith Thompson

6
@ KeithThompson ไม่เกี่ยวกับการเขียนโค้ดที่ถูกต้องในหลายภาษา ฉันคิดว่ามันเกี่ยวกับการหลีกเลี่ยงการตีความที่ผิดพลาดระหว่างนักพัฒนาที่มีภูมิหลังต่างกัน
Mauro Sampietro

6
@ แซม: ทั้งสองwhile (1)และfor (;;)เป็นสำนวนทั่วไปสำหรับลูปที่ไม่มีที่สิ้นสุดใน C. ทุกคนที่อ่านโปรแกรม C ที่มีปัญหาในการทำความเข้าใจอาจมีปัญหากับรหัสที่เหลือ มันไม่คุ้มค่าที่จะเขียนโค้ด C ที่คนที่ไม่รู้จักสามารถอ่าน C. ได้ง่าย
Keith Thompson

6
@ KeithThompson ในขณะที่ผู้อ่านที่มีความสามารถของ C ควรจะคุ้นเคยกับสำนวนทั้งสองอย่างนี้จะมีประโยชน์ถ้านักเขียนเป็นโปรแกรมเมอร์หลายภาษา ในงานสุดท้ายของฉันฉันทำงานใน JS, ActionScript และ PHP ทุกวันและการรวมวิธีการหนึ่งที่เขียนโค้ด (ซึ่งเหมาะสมที่จะทำ) สามารถทำให้การเขียนโปรแกรมเร็วขึ้นและบำรุงรักษาง่ายขึ้น
Ionoclast Brigham

21

ผมเองชอบfor (;;)สำนวน while (TRUE)(ซึ่งจะรวบรวมรหัสเดียวกับ

ใช้while (TRUE)อาจจะอ่านได้มากขึ้นในอีกแง่หนึ่งฉันได้ตัดสินใจที่จะใช้for (;;)สำนวนเพราะมันยืนออก

สร้างห่วงอนันต์ควรจะสังเกตเห็นได้ง่ายหรือเรียกว่าออกมาในรหัสและผมเองคิดว่าfor (;;)สไตล์ไม่นี้บิตดีกว่าหรือwhile (TRUE)while (1)

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


17

ฉันเคยเห็นบางคนชอบเพราะมี #define บางแห่งเช่นนี้:

#define EVER ;;

ซึ่งทำให้พวกเขาเขียนสิ่งนี้:

for (EVER)
{
    /* blah */
}

24
ฉันก็เห็นเช่นกัน แต่มันก็ไม่ใช่เหตุผลที่ดีสำหรับการเลือกมัน ในฐานะผู้ดูแลคุณยังต้องตรวจสอบคำจำกัดความของแมโครเพื่อให้แน่ใจว่าทำในสิ่งที่คุณคาดหวังในขณะที่รหัสดั้งเดิมนั้นชัดเจนเพียงพอ RTOS VxWorks มีการFOREVERกำหนดมาโครfor(;;)แต่ก็ไม่ดีกว่า ไม่ควรใช้มาโคร IMO เพื่อ 'คิดค้น' ภาษาใหม่
Clifford

8
ที่จริงแล้วจุดประสงค์ของมาโครในบางภาษาคือการสร้างไวยากรณ์ใหม่ แต่ไม่ว่า 'for (EVER)' ใน C / C ++ นั้นเป็นสิ่งที่เลวร้าย
Dan Olson

15
บางคนทำสิ่งที่ตลกเช่นถ้าพวกเขาเช่นปาสคาลที่พวกเขาพูดและ#define BEGIN { #define END }ฉันเคยเห็น#define DONKEYS_FLY (0)ดังนั้นพวกเขาจึงสามารถพูดif DONKEYS_FLY ...ได้ ใครบอกว่าซอฟต์แวร์มีความน่าเบื่อ?
Mike Dunlavey

11
ในแคลิฟอร์เนียฉันเชื่อว่าคุณต้อง #define สำหรับ (;;) LIKE_FOREVER
Martin Beckett

1
ฉันไม่สามารถต้านทาน: #define never while(0)และ#define always
alfC

16

เกี่ยวกับ (ถ้าภาษาของคุณรองรับ):

start:
/* BLAH */
goto start;

... ซึ่งควรสร้างผลลัพธ์ที่เหมือนกันในมือของผู้แปลที่สมเหตุสมผล
Ben Zotto

9
+1! มันไม่ได้ช่วยแก้ไขgotoข้อเสียมากมาย แต่ถ้าอัลกอริทึมที่คุณพยายามจะนำมาใช้นั้นมาจากแผนภูมิการไหลนี่เป็นการแปลที่ตรงที่สุด
Edmund

4
โดยส่วนตัวฉันใช้มุมมองที่เป็นประโยชน์เกี่ยวกับข้ามไป ไม่มีแร็พเตอร์ แร็พเตอร์เป็นคน และเป็นคนที่เริ่มใช้ goto เพื่อสร้างรหัสสปาเก็ตตี้ นอกจากนี้เอาต์พุตที่ประกอบสำหรับลูปจะดูสวยมากเช่นนี้ ชุดคำสั่งสำหรับคอมพิวเตอร์ไม่มีแนวคิด "สำหรับ" หรือ "ในขณะที่" เพียงแค่ "กระโดด"
josaphatv

ไม่เคยใช้goto
Edward Karak

สิ่งที่ดีจริง ๆgotoคือคุณไม่ต้องกังวลกับคนที่เพิ่ม a breakเพื่อทำให้ลูปของคุณไม่มีที่สิ้นสุด (ยกเว้นว่าคุณอยู่ในอีกวงหนึ่งwhileหรือforแน่นอน ... )

12

ไม่มีความแตกต่างในแง่ของรหัสเครื่องที่สร้างขึ้น

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


6
ขึ้นอยู่กับภาษาของคุณ for(;;)เป็นวิธีดั้งเดิมในการทำเช่นนี้ใน C และ C ++ while(true)ดูเหมือนว่าจะเป็นการประชุมใน C # และ Java และภาษาอื่น ๆ ไมล์สะสมของคุณอาจแตกต่างกันไป
Billy ONeal

9
ใช่และบางคนที่ไม่คุ้นเคยกับ C หรือ C ++ อาจพบว่า STRING_SCAN_FORMATTED อ่านได้ง่ายกว่า sscanf แต่คุณไม่เห็นใครใส่ #define STRING_SCAN_FORMATTED sscanf ที่ด้านบนของรหัส
ta.speot.is

4
ฉันจะบอกว่าวิธีการทำสิ่งที่ดีกว่านั้นเป็นสิ่งที่นักพัฒนาซอฟต์แวร์ของคุณอ่านได้ดีที่สุด มิฉะนั้นคุณต้องมีนักพัฒนาที่ดีกว่าจริงๆ
jalf

5
@ ส่วนที่: ถ้าใครไม่คุ้นเคยกับ C ++ พอที่จะรับรู้สำนวนนั้นสำหรับสิ่งที่มันเป็นแล้วพวกเขาต้องอยู่ห่างจาก codebase ของฉัน
Billy ONeal

4
ฉันยอมรับว่าวิธีการใช้สำนวนควรเป็นวิธีที่อ่านง่ายที่สุด นี่คือเหตุผลที่วิธีการใช้สำนวนต้องท้าทายและเปลี่ยนแปลงเสมอเมื่อภาษาและการปฏิบัติพัฒนาขึ้น ต้องใช้เวลาหลายปีกว่าที่รูปแบบการเขียนรหัส "สำนวน" K&R ที่น่ากลัวจะถูกแทนที่ด้วยรูปแบบที่ทันสมัยอ่านได้ง่ายขึ้น แต่ยังคงเกิดขึ้น
Jason Williams

11

ไม่ใช่แค่รูปแบบที่รู้จักกันดี แต่เป็นสำนวนมาตรฐานใน C (และ C ++)


3
ใช่และฉันคิดว่าคอมไพเลอร์บางเตือนในเหตุผลเดียวกันพวกเขาทำบนwhile (true) if (true)
Steven Sudit

11
while(true)

สร้างคำเตือนด้วย Visual Studio (เงื่อนไขเป็นค่าคงที่) สถานที่ส่วนใหญ่ที่ฉันได้ทำงานรวบรวมการผลิตสร้างด้วยคำเตือนเป็นข้อผิดพลาด ดังนั้น

for(;;)

เป็นที่ต้องการ


7
คุณใช้ Visual Studio รุ่นใด ด้วยปี 2008 ฉันไม่ได้รับคำเตือนนี้แม้จะอยู่ที่ระดับเตือน 4
Jörgen Sigvardsson

11

ทั้งคู่ควรเหมือนกันถ้าคอมไพเลอร์ของคุณได้รับการปรับให้เหมาะสม เพื่ออธิบายสิ่งที่ฉันหมายถึงโดยการเพิ่มประสิทธิภาพนี่คือตัวอย่างรหัสที่เขียนใน MSVC 10:

int x = 0;

while(true) // for(;;)
{
    x +=1;

    printf("%d", x);
}

ถ้าคุณสร้างมันในโหมดดีบั๊ก ( โดยไม่มีการปรับแต่งใด ๆ (/ Od) ) แสดงความแตกต่างที่ชัดเจน มีคำแนะนำพิเศษสำหรับการเป็นภายในสภาพtruewhile

while(true)
00D313A5  mov         eax,1                //extra 
00D313AA  test        eax,eax              //extra
00D313AC  je          main+39h (0D313B9h)  //extra
    {
        x +=1;
00D313AE  mov         eax,dword ptr [x]  
00D313B1  add         eax,1  
00D313B4  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D313B7  jmp         main+25h (0D313A5h)  


for(;;)
    {
        x +=1;
00D213A5  mov         eax,dword ptr [x]  
00D213A8  add         eax,1  
00D213AB  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D213AE  jmp         main+25h (0D213A5h)  

อย่างไรก็ตามหากคุณสร้างรหัสในโหมด Release (โดยค่าเริ่มต้น ความเร็วสูงสุด (/ O2) ) คุณจะได้ผลลัพธ์เดียวกันทั้งคู่ ลูปทั้งสองจะลดลงเป็นคำสั่งกระโดดหนึ่งครั้ง

for(;;)
    {
        x +=1;
01291010  inc         esi  

        printf("%d", x);
    ...
    }
0129101C  jmp         main+10h (1291010h)  

    while(true)
    {
        x +=1;
00311010  inc         esi  

        printf("%d", x);
    ...
    }
0031101C  jmp         main+10h (311010h)  

ไม่ว่าคุณจะใช้งานแบบใดก็ตามไม่ว่าจะเป็นคอมไพเลอร์ที่ดีพร้อมการเพิ่มประสิทธิภาพความเร็วก็ตาม


นี่เป็นจุดที่ดีมากจริงๆ! หากไม่มีการปรับให้เหมาะสมแม้แต่คอมไพเลอร์สมัยใหม่ก็จะแตกต่างกันไปตามคำแนะนำต่าง ๆ

9

มันเป็นเรื่องของความชอบส่วนตัวซึ่งเป็นวิธีที่เร็วกว่า โดยส่วนตัวแล้วฉันเป็นนักออกแบบระบบสัมผัสและไม่เคยดูที่แป้นพิมพ์ของฉันในระหว่างการเขียนโปรแกรม - ฉันสามารถใช้แป้นพิมพ์ทั้ง 104 ปุ่มบนแป้นพิมพ์ได้

ฉันพบว่าพิมพ์เร็วกว่า "ในขณะที่ (จริง)"

ฉันเพิ่มการวัดการเคลื่อนไหวนิ้วของจิตใจและรวมพวกมันเข้าด้วยกัน "for (;;)" มีความกว้างประมาณ 12 คีย์ของการเคลื่อนไหวไปมาและหลังที่สี่ (ระหว่างปุ่มโฮมและปุ่มและระหว่างปุ่มโฮมและปุ่ม SHIFT) "ในขณะที่ (TRUE)" มีความกว้างประมาณ 14 คีย์ของการเคลื่อนไหวกลับและ ที่สี่

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

(เกณฑ์มาตรฐาน TypingTest.com ของฉัน = 136 WPM)


3
ฉันเชื่อว่า OP หมายถึงความเร็วของรันไทม์ไม่ใช่ความเร็วในการพิมพ์

ฉันรู้ว่า. แค่ต้องครอบคลุมฐานนั้นด้วย
Mark Rejhon

7
S / การตั้งค่าส่วนตัว / นิสัยของแต่ละบุคคล /
SAMB

@SamB: แสดงความคิดเห็นลงคะแนนสำหรับ s /// xD และใช่แม้ว่าฉันจะแนะนำว่าอาจเป็นเพราะความเร็วของรันไทม์ แต่ฉันไม่รู้คำตอบที่แท้จริง ถ้าเป็นแบบนี้ฉันคงมีความสุข
Chris Cooper

เรียกใช้time head -10 >/dev/nullพิมพ์แต่ละ 10 ครั้งและวัดผลลัพธ์ ฉันพนันได้เลยว่าคุณจะเร็วขึ้นfor(;;)ถ้าคุณไม่โกง ฉันประมาณ 14%
PSkocik

6

คำตอบที่ดีทั้งหมด - พฤติกรรมควรเหมือนกันทุกประการ

อย่างไร - เพียงแค่สมมติว่ามันสร้างความแตกต่าง สมมติว่าหนึ่งในนั้นใช้คำแนะนำเพิ่มเติม 3 คำต่อการวนซ้ำ

คุณควรสนใจไหม

ถ้าสิ่งที่คุณทำในลูปนั้นแทบจะไม่มีอะไรเลยซึ่งแทบจะไม่เกิดเลย

จุดของฉันคือมีการเพิ่มประสิทธิภาพขนาดเล็กและการเพิ่มประสิทธิภาพแมโคร การเพิ่มประสิทธิภาพขนาดเล็กเป็นเหมือน "การตัดผมเพื่อลดน้ำหนัก"


3
คุณเห็นคนที่บอกว่าชอบ++iมากกว่าบ่อยแค่ไหนi++ไหน?
Dennis Zickefoose

7
@Dennis Zickefoose: ความแตกต่างระหว่าง++iและi++อาจมีนัยสำคัญหากiเป็นตัวอย่างของคลาสแทนที่จะเป็นบิวด์อินและคอมไพเลอร์ไม่ได้ใช้การปรับให้เหมาะสมที่สุด คำแนะนำคือการได้รับนิสัยเพื่อที่จะไม่ไล่คุณออกเมื่อมันนับ
Clifford

5
สิ่งที่เกี่ยวกับ++ivs i++คือคุณไม่ต้องเสียค่าใช้จ่ายใด ๆ เลยในการเพิ่มประสิทธิภาพ จริงในกรณีส่วนใหญ่มันไม่ได้สร้างความแตกต่างอย่างแน่นอน แต่พวกมันก็พิมพ์ได้ง่ายพอ ๆ กันดังนั้นทำไมไม่ชอบค่าเริ่มต้นที่มีประสิทธิภาพมากที่สุด? และฉันก็คิดเหมือนกันว่าใช้ตรงนี้ หากหนึ่งเป็นบิตขนาดเล็กได้เร็วขึ้นกว่าที่อื่น ๆ ทำไมไม่ไปได้เร็วขึ้นหรือไม่ เราจะเสียอะไรไปจากการทำเช่นนี้? ทั้งสองค่อนข้างง่ายต่อการอ่านและพิมพ์
jalf

2
@Dennis Zickefoose: ถูกต้อง ฉันเห็นว่ามีมากใน SO และความคิดเห็นของ Clifford นั้นถูกต้อง นอกจากนี้ยังมีสิ่งที่ฉันไม่เห็นมากในดังนั้นและที่เป็นวิธีการที่จะทำมหภาคเพิ่มประสิทธิภาพเช่น 43X speedup: stackoverflow.com/questions/926266/... ดังนั้นฉันสงสัยเกี่ยวกับลำดับความสำคัญของเรา
Mike Dunlavey

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

5

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

อย่างไรก็ตามฉันขอแนะนำให้คุณชอบfor(;;)ด้วยเหตุผลดังต่อไปนี้:

  • คอมไพเลอร์จำนวนหนึ่งที่ฉันใช้จะสร้างคำเตือนนิพจน์คงที่ในขณะที่ (จริง) พร้อมการตั้งค่าระดับคำเตือนที่เหมาะสม

  • ในตัวอย่างของคุณมาโคร TRUE อาจไม่ได้รับการกำหนดตามที่คุณคาดหวัง

  • มีสายพันธุ์ที่เป็นไปได้หลายที่ไม่มีที่สิ้นสุดในขณะที่ห่วงเช่นwhile(1), while(true), while(1==1)ฯลฯ .; ดังนั้นfor(;;)มีแนวโน้มที่จะส่งผลให้ความมั่นคงมากขึ้น


TRUE อาจจะไม่ #define TRUE 1 แต่ฐานรหัสใด ๆ ในการที่while(TRUE)จะประเมินเป็นไม่น่าจะได้รับประโยชน์จากwhile(0) for(;;)
Justin

@ จัสติน: ฉันเห็นด้วยมันจะผิดปกติอย่างแท้จริงและมันไม่ใช่จุดแข็งที่สุดของทั้งสามข้อโต้แย้ง แต่ Bjarne Stoustrup ใช้อาร์กิวเมนต์ที่คล้ายกันเพื่อหลีกเลี่ยงแมโคร NULL ใน C ++ while(true)ควรเป็นที่ต้องการในกรณีใด ๆ ใน C ++ boolสงวนไว้และใน C ถูกกำหนดใน C stdbool.h (ทำให้ปลอดภัยน้อยกว่าใน C) for(;;)ลบข้อสงสัยทั้งหมด
Clifford

5
for(;;Sleep(50))
{
    // Lots of code
}

ชัดเจนกว่า:

while(true)
{
    // Lots of code
    Sleep(50);
}

Sleep()ไม่ว่านี้ถ้าคุณไม่ได้ใช้


1
มันเป็นรหัสที่ไม่ดีแช่งควรใช้ตัวจับเวลาแทนการนอนหลับดังนั้นจึงเป็นตัวอย่างที่ไม่ดี
ST3

12
@ ST3 - ใช่คุณพูดถูก รหัสของฉันแย่มาก ฉันควรพยายามให้มากขึ้นในครั้งต่อไปที่ฉันจะวนซ้ำไม่สิ้นสุด
กองเรือ

1
@Frammo - ขึ้นอยู่กับระบบปฏิบัติการของคุณ แต่โดยทั่วไปแล้วจะเป็นเช่นนั้นtimerService.scheduleRepeating (50, [] () { /* lots of code */ });
Periata Breatta

2
ไม่มีสิ่งใดที่สะอาดเกี่ยวกับการเรียกใช้ฟังก์ชั่นอย่างสลีปภายในของ for for loop อย่างนั้น
Greg

1
OMG, timerService.scheduleRepeating (50, [] () {}) นั้นง่ายกว่ามากในการพิมพ์และทำความเข้าใจแล้วนอน (50)
เย็น Javelin

4

วนรอบ "ตลอดไป" เป็นที่นิยมในระบบฝังตัวเป็นวนรอบด้านหลัง บางคนใช้มันเป็น:

for (; ;)
{
 // Stuff done in background loop
}

และบางครั้งมันถูกนำไปใช้เป็น:

while (TRUE /* or use 1 */)
{
 // Stuff done in background loop
}

และการดำเนินการอื่นคือ:

do
{
 // Stuff done in background loop
} while (1 /* or TRUE */);

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


8
หากคอมไพเลอร์สร้างรหัสที่แตกต่างกันสำหรับเหล่านั้นก็ถึงเวลาที่จะทิ้งคอมไพเลอร์และรับหนึ่งรหัสจากสองทศวรรษที่ผ่านมา
GManNickG

5
"เวลาในการดำเนินการของลูปไม่ใช่เรื่องใหญ่นักเนื่องจากลูปเหล่านี้ดำเนินต่อไปตลอดกาล" - ฟังดูผิดมากสำหรับฉัน ..
Blindy

3
@Blindy - เพราะมันเป็นความผิดอะไรของความกังวลคือส่วนของรันไทม์ใช้เวลาในการประมวลผลบ่วงตรรกะหรือจำนวนบ่วงตรรกะต่อหน่วยของการทำงานที่มีประโยชน์ที่ไม่ได้รับการช่วยเหลือจากวงเป็นอนันต์
เบนยต์

3

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


ฉันสนใจความเร็ว โดยเฉพาะอย่างยิ่งหากมีการเพิ่มประสิทธิภาพซึ่งจะส่งผลกระทบต่อเวลาที่ไม่มีที่สิ้นสุดของฉันรหัส
Kowalski

2

เหตุผลที่สำคัญที่สุดในการใช้ "for (;;)" คือความกลัวในการใช้ "while (TRUE)" เมื่อคุณทำการเขียนโปรแกรมเชิงสำรวจ มันง่ายกว่าที่จะควบคุมปริมาณการทำซ้ำด้วย "สำหรับ" และยังง่ายกว่าในการแปลงลูป "for" เป็นอนันต์

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

    for(int i=0;i<1000;i++) recursiveFunction(oneParam);

เมื่อฉันแน่ใจว่าฟังก์ชั่นของฉันแล้วฉันจะแปลงเป็นวงไม่สิ้นสุด:

    for(;;) recursiveFunction(oneParam);

3
ลูปแรกมีข้อผิดพลาดทางไวยากรณ์ (ไม่มีเครื่องหมายอัฒภาค)
Jens

3
ฮา! จึงแสดงให้เห็นถึงข้อเสียของ (;;);)
แอนดรู
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.