trong khi (1) Vs. cho (;;) Có sự khác biệt về tốc độ không?


154

Phiên bản dài ...

Một đồng nghiệp đã khẳng định ngày hôm nay sau khi thấy tôi sử dụng while (1)tập lệnh Perl for (;;)nhanh hơn. Tôi lập luận rằng họ nên giống nhau với hy vọng rằng người phiên dịch sẽ tối ưu hóa mọi khác biệt. Tôi thiết lập một tập lệnh sẽ chạy 1.000.000.000 cho các vòng lặp lặp và cùng số vòng lặp while và ghi lại thời gian giữa. Tôi không thể tìm thấy sự khác biệt đáng kể. Đồng nghiệp của tôi nói rằng một giáo sư đã nói với anh ta rằng họ while (1)đang làm một phép so sánh 1 == 1for (;;)không. Chúng tôi lặp lại thử nghiệm tương tự với số lần lặp 100 lần với C ++ và sự khác biệt là không đáng kể. Tuy nhiên, đây là một ví dụ đồ họa về việc mã được biên dịch nhanh hơn bao nhiêu so với ngôn ngữ kịch bản.

Phiên bản ngắn...

Có bất kỳ lý do để thích while (1)hơn một for (;;)nếu bạn cần một vòng lặp vô hạn để thoát ra?

Lưu ý: Nếu nó không rõ ràng từ câu hỏi. Đây hoàn toàn là một cuộc thảo luận học thuật thú vị giữa một vài người bạn. Tôi biết rằng đây không phải là một khái niệm siêu quan trọng mà tất cả các lập trình viên nên thống nhất. Cảm ơn tất cả các câu trả lời tuyệt vời mà tôi (và tôi chắc chắn rằng những người khác) đã học được một vài điều từ cuộc thảo luận này.

Cập nhật: Đồng nghiệp đã nói ở trên cân nhắc với một phản hồi bên dưới.

Trích dẫn ở đây trong trường hợp nó được chôn cất.

Nó đến từ một lập trình viên lắp ráp AMD. Ông tuyên bố rằng các lập trình viên C (poeple) không nhận ra rằng mã của họ không hiệu quả. Anh ấy nói hôm nay mặc dù, trình biên dịch gcc rất tốt và đưa những người như anh ấy ra khỏi doanh nghiệp. Ông nói ví dụ, và nói với tôi về while 1vs for(;;). Bây giờ tôi sử dụng nó theo thói quen nhưng gcc và đặc biệt là thông dịch viên sẽ thực hiện cùng một thao tác (nhảy bộ xử lý) cho cả hai ngày này, vì chúng được tối ưu hóa.


4
Tôi tò mò. Tại sao cần một vòng lặp vô hạn trong một tập lệnh perl? Rõ ràng là bạn không lập trình trình điều khiển hoặc hệ thống ... Infinite khá yên tĩnh :-)
Luc M

125
Vòng lặp vô hạn nào là nhanh nhất? LOL ... "Máy tính mới của tôi rất nhanh, nó chạy một vòng lặp vô hạn chỉ trong chưa đầy một giờ ..." ;-)
Arjan Einbu

8
Đó có phải là một giáo sư xã hội học đã nói với anh ấy điều đó? Trong kỷ nguyên hiện đại, mã bạn nhập không phải là thứ mà máy tính sẽ thấy.
brian d foy

5
tôi hy vọng lượng thời gian bạn cần để kiểm tra việc này dài hơn nhiều so với lượng thời gian có khả năng tiết kiệm bằng cách biết cái nào nhanh hơn, nếu có. ngay cả khi bạn khấu hao nó trong cả cuộc đời lập trình của bạn.
Peter Recore

4
Tại sao trình biên dịch sẽ tạo mã để thực hiện kiểm tra mà nó biết không có tác dụng phụ và kết quả mà trình biên dịch đã biết? Điều đó không có ý nghĩa.
David Schwartz

Câu trả lời:


218

Trong perl, chúng dẫn đến các opcodes giống nhau:

$ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

Tương tự như vậy trong GCC:

#include <stdio.h>

void t_while() {
    while(1)
        printf("foo\n");
}

void t_for() {
    for(;;)
        printf("foo\n");
}

    .file   "test.c"
    .section    .rodata
.LC0:
    .string "foo"
    .text
.globl t_while
    .type   t_while, @function
t_while:
.LFB2:
    pushq   %rbp
.LCFI0:
    movq    %rsp, %rbp
.LCFI1:
.L2:
    movl    $.LC0, %edi
    call    puts
    jmp .L2
.LFE2:
    .size   t_while, .-t_while
.globl t_for
    .type   t_for, @function
t_for:
.LFB3:
    pushq   %rbp
.LCFI2:
    movq    %rsp, %rbp
.LCFI3:
.L5:
    movl    $.LC0, %edi
    call    puts
    jmp .L5
.LFE3:
    .size   t_for, .-t_for
    .section    .eh_frame,"a",@progbits
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .string "zR"
    .uleb128 0x1
    .sleb128 -8
    .byte   0x10
    .uleb128 0x1
    .byte   0x3
    .byte   0xc
    .uleb128 0x7
    .uleb128 0x8
    .byte   0x90
    .uleb128 0x1
    .align 8
.LECIE1:
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB2
    .long   .LFE2-.LFB2
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI0-.LFB2
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI1-.LCFI0
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE1:
.LSFDE3:
    .long   .LEFDE3-.LASFDE3
.LASFDE3:
    .long   .LASFDE3-.Lframe1
    .long   .LFB3
    .long   .LFE3-.LFB3
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI2-.LFB3
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI3-.LCFI2
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE3:
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

Vì vậy, tôi đoán câu trả lời là, chúng giống nhau trong nhiều trình biên dịch. Tất nhiên, đối với một số trình biên dịch khác, điều này có thể không nhất thiết phải như vậy, nhưng rất có thể mã bên trong vòng lặp sẽ đắt hơn vài nghìn lần so với chính vòng lặp, vậy ai quan tâm?


15
thử với B :: Depough, depars a infinite for loop trả về một vòng lặp while: P
Kent Fredric

27
"Trong perl, chúng dẫn đến cùng một opcodes" ... có, nhưng cái nào nhanh hơn? :-)
Tin Man

6
Tôi thích rằng gcc thay thế đặt () cho printf (), vì chỉ có một đối số và do đó không có gì để định dạng - nhanh hơn và an toàn hơn! (gcc cũng kiểm tra các thẻ định dạng đối với danh sách đối số biến.)
Lee D

@ The Tin Man: chúng tương đương nhau, vì máy tính thực hiện các thao tác chính xác tương tự: P
BlackBear

1
@snap, nó không 'hoàn toàn' không chính xác, nó chỉ tập trung vào chi phí thời gian chạy. Tôi không thể tưởng tượng loại tình huống nào sẽ dẫn đến thời gian phân tích các vòng lặp vô hạn là yếu tố quyết định chính trong việc chương trình của bạn chạy nhanh như thế nào
bdonlan

55

Sử dụng GCC, cả hai dường như biên dịch theo cùng một ngôn ngữ lắp ráp:

L2:
        jmp     L2

20
Sử dụng GCC với tùy chọn -S (lắp ráp, không liên kết)
Martin Côte

54

Không có nhiều lý do để thích cái này hơn cái kia. Tôi nghĩ rằng while(1)và đặc biệt while(true)là dễ đọc hơn for(;;), nhưng đó chỉ là sở thích của tôi.


94
#define EVER ;; cho (EVER) Tôi luôn thấy điều đó thật thú vị.
Tom

19
Làm thế nào về #define bao giờ (;;) mãi mãi;
Martin Côte

16
Cả hai dường như dễ đọc hơn trên bề mặt, nhưng tôi cố gắng không xác định các từ khóa mới cho lập trình viên bảo trì của tôi (thường là tôi) để gãi đầu.
Lập hóa đơn cho thằn lằn

13
@Martin sẽ không hoạt động, vì # định nghĩa không thay thế trong mã thông báo và foreverđó là mã thông báo riêng.
Lily Chung

2
"Tôi cố gắng không xác định các từ khóa mới cho việc bảo trì của mình" - nếu chỉ có nhiều người có thái độ đó, tôi sẽ không nắm bắt được tất cả các shenanigans bóng ma và ma thuật này mỗi khi tôi quay lại!
tchrist

31

Không có sự khác biệt theo tiêu chuẩn. 6.5.3 / 1 có:

Tuyên bố cho

for ( for-init-statement ; conditionopt ; expressionopt ) statement

tương đương với

{
  for-init-statement
  while ( condition ) {
    statement
    expression ;
  }
}

Và 6.5.3 / 2 có:

Một trong hai hoặc cả hai điều kiện và biểu thức có thể được bỏ qua. Một điều kiện bị thiếu làm cho mệnh đề while ngụ ý tương đương với while (true).

Vì vậy, theo tiêu chuẩn C ++, mã:

for (;;);

hoàn toàn giống như:

{
  while (true) {
    ;
    ;
  }
}

4
Điều đó hoàn toàn không liên quan đến mã được tạo hoặc hiệu suất. Các tiêu chuẩn chỉ xác định chức năng. Tất nhiên, hiệu suất sẽ là như nhau.
Potatoswatter

1
Tôi không tin rằng sự khác biệt về hiệu suất vi phạm quy tắc như thể. Nếu đúng như vậy, thì trình biên dịch sẽ không được phép tăng tốc mã của bạn theo quy tắc as-if, ví dụ bằng cách sắp xếp lại các câu lệnh độc lập. Trình biên dịch trong thực tế làm chính xác điều đó. Nhưng bản sao của tiêu chuẩn của tôi là trên lầu.
Steve Jessop

28

Trình biên dịch Visual C ++ được sử dụng để phát ra cảnh báo cho

while (1) 

(biểu thức không đổi) nhưng không cho

for (;;)

Tôi đã tiếp tục thực hành thích for (;;)vì lý do đó, nhưng tôi không biết nếu trình biên dịch vẫn làm điều đó những ngày này.


cảnh báo có thể là do bạn đã sử dụng trong khi (1) thay vì while (đúng)
jrharshath

16
đúng là một hằng số. while (true) là một biểu thức không đổi. Đối với bất kỳ ai quan tâm, cảnh báo C4127 được ghi lại ở đây: msdn.microsoft.com/en-us/l
sean e

Có, cảnh báo vẫn còn cho cả 1 và đúng. Đó là lý do tại sao tôi luôn luôn sử dụng cho (;;)
Elviss Strazdins

26

for(;;) là một ký tự ít hơn để gõ nếu bạn muốn đi theo hướng đó để tối ưu hóa mọi thứ.


21
Tốt để biết chơi golf. Nếu không, một lý do kém để chọn một cú pháp.
Adam Bellaire

@AdamBellaire Sự căng thẳng thường làm tăng khả năng đọc, trên ngưỡng kỹ năng nhất định.
Vector Gorgoth

20

Turbo C với trình biên dịch cũ này for(;;)dẫn đến mã nhanh hơn sau đó while(1).

Ngày nay gcc, trình biên dịch Visual C (tôi nghĩ là hầu hết tất cả) tối ưu hóa tốt và CPU với 4,7 MHz hiếm khi được sử dụng.

Trong những ngày đó, a for( i=10; i; i-- )nhanh hơn for( i=1; i <=10; i++ ), bởi vì so sánh ilà 0, dẫn đến Bước nhảy có điều kiện CPU-Zero-Flag. Và Zero-Flag đã được sửa đổi với thao tác giảm dần cuối cùng ( i-- ), không cần thêm thao tác cmp nào.

    call    __printf_chk
    decl    %ebx          %ebx=iterator i 
    jnz     .L2
    movl    -4(%ebp), %ebx
    leave

và ở đây for(i=1; i<=10; i++)với thêm cmpl:

    call    __printf_chk
    incl    %ebx
    cmpl    $11, %ebx
    jne     .L2
    movl    -4(%ebp), %ebx
    leave

13

Đối với tất cả những người tranh luận, bạn không nên sử dụng indefinte trong khi các vòng lặp và đề xuất các công cụ giả như sử dụng goto mở (nghiêm túc, ouch)

while (1) {
     last if( condition1 );
     code();
     more_code(); 
     last if( condition2 ); 
     even_more_code(); 
}

Không thể thực sự được đại diện hiệu quả bất kỳ cách nào khác. Không phải không tạo ra một biến thoát và thực hiện phép thuật đen để giữ cho nó được đồng bộ hóa.

Nếu bạn có xu hướng sử dụng cú pháp goto-esque nhiều hơn, hãy sử dụng một cái gì đó lành mạnh để giới hạn phạm vi.

flow: { 

   if ( condition ){ 
      redo flow;
   }
   if ( othercondition ){ 
       redo flow;
   }
   if ( earlyexit ){ 
       last flow;
   }
   something(); # doesn't execute when earlyexit is true 
}

Cuối cùng, tốc độ không quan trọng

Lo lắng về tốc độ hiệu quả của các cấu trúc vòng lặp khác nhau là một sự lãng phí lớn thời gian. Tối ưu hóa sớm thông qua và thông qua. Tôi không thể nghĩ về bất kỳ tình huống nào tôi từng thấy khi mã hồ sơ tìm thấy các nút thắt cổ chai trong lựa chọn xây dựng vòng lặp của tôi.

Nói chung nó là cách của vòng lặp và những gì của vòng lặp.

Bạn nên "tối ưu hóa" để dễ đọc và cô đọng, và viết bất cứ điều gì tốt nhất để giải thích vấn đề cho người hút nghèo tiếp theo tìm thấy mã của bạn.

Nếu bạn sử dụng thủ thuật "goto LABEL" mà ai đó đã đề cập và tôi phải sử dụng mã của bạn, hãy chuẩn bị ngủ với một mắt mở, đặc biệt là nếu bạn làm điều đó nhiều lần, bởi vì những thứ đó tạo ra mã spaghetti khủng khiếp .

Chỉ vì bạn có thể tạo mã spaghetti không có nghĩa là bạn nên


9

Từ Stroustrup, TC ++ PL (ấn bản thứ 3), §6.1.1:

Ký hiệu tò mò for (;;)là cách tiêu chuẩn để xác định một vòng lặp vô hạn; bạn có thể phát âm nó "mãi mãi". [...] while (true)Là một thay thế.

Tôi thích for (;;).


9

Nếu trình biên dịch không thực hiện bất kỳ tối ưu hóa nào, for(;;)sẽ luôn nhanh hơn while(true). Điều này là do while-statement đánh giá điều kiện mọi lúc, nhưng for-statement là một bước nhảy vô điều kiện. Nhưng nếu trình biên dịch tối ưu hóa luồng điều khiển, nó có thể tạo ra một số opcodes. Bạn có thể đọc mã tháo gỡ rất dễ dàng.

PS bạn có thể viết một vòng lặp vô hạn như thế này:

#define EVER ;;
  //...
  for (EVER) {
    //...
  }

Trong thời đại ngày nay, không nên thay thế EVER bằng EVS (nói chuyện tuổi teen)! Nghiêm túc mặc dù tôi chỉ đơn giản là sử dụng cho (;;) {}. Tôi đã đọc trực tuyến từ lâu về sự khác biệt giữa hai người (khi tôi còn trẻ và thực sự không biết họ giống nhau) và chỉ bị mắc kẹt với những gì tôi đọc.
Bja

8

Tôi đã nghe về điều này một lần.

Nó đến từ một lập trình viên lắp ráp AMD. Ông tuyên bố rằng các lập trình viên C (người dân) không nhận ra rằng mã của họ không hiệu quả. Anh ấy nói hôm nay mặc dù, trình biên dịch gcc rất tốt và đưa những người như anh ấy ra khỏi doanh nghiệp. Ông nói ví dụ, và nói với tôi về while 1vs for(;;). Bây giờ tôi sử dụng nó theo thói quen nhưng gcc và đặc biệt là thông dịch viên sẽ thực hiện cùng một thao tác (nhảy bộ xử lý) cho cả hai ngày này, vì chúng được tối ưu hóa.


5

Trong một bản dựng được tối ưu hóa của một ngôn ngữ được biên dịch, sẽ không có sự khác biệt đáng kể nào giữa hai ngôn ngữ này. Cuối cùng, không nên thực hiện bất kỳ so sánh nào trong thời gian chạy, chúng sẽ chỉ thực thi mã vòng lặp cho đến khi bạn thoát khỏi vòng lặp theo cách thủ công (ví dụ với a break).


3

Tôi ngạc nhiên rằng không ai được kiểm tra đúng cách for (;;)so với while (1)perl!

Vì perl là ngôn ngữ được diễn giải, thời gian để chạy tập lệnh perl không chỉ bao gồm giai đoạn thực thi (mà trong trường hợp này là giống nhau) mà còn của giai đoạn diễn giải trước khi thực hiện. Cả hai giai đoạn này phải được tính đến khi so sánh tốc độ.

May mắn thay, perl có một mô-đun Điểm chuẩn thuận tiện mà chúng ta có thể sử dụng để thực hiện một điểm chuẩn như sau:

#!/usr/bin/perl -w

use Benchmark qw( cmpthese );

sub t_for   { eval 'die; for (;;) { }'; }
sub t_for2  { eval 'die; for (;;)  { }'; }
sub t_while { eval 'die; while (1) { }'; }

cmpthese(-60, { for => \&t_for, for2 => \&t_for2, while => \&t_while });

Lưu ý rằng tôi đang thử nghiệm hai phiên bản khác nhau của vòng lặp vô hạn: một phiên bản ngắn hơn vòng lặp while và một phiên bản khác có không gian thừa để làm cho nó có cùng độ dài với vòng lặp while.

Trên Ubuntu 11.04 x86_64 với perl 5.10.1 tôi nhận được các kết quả sau:

          Tỷ lệ cho for2 trong khi
cho 100588 / s - -0% -2%
for2 100937 / s 0% - -1%
trong khi 102147 / s 2% 1% -

Vòng lặp while rõ ràng là người chiến thắng trên nền tảng này.

Trên FreeBSD 8.2 x86_64 với perl 5.14.1:

         Tỷ lệ cho for2 trong khi
cho 53453 / s - -0% -2%
for2 53552 / s 0% - -2%
trong khi 54564 / s 2% 2% -

Trong khi vòng lặp là người chiến thắng ở đây quá.

Trên FreeBSD 8.2 i386 với perl 5.14.1:

         Tỷ lệ trong khi for2
trong khi 24311 / s - -1% -1%
cho 24481 / s 1% - -1%
for2 24637 / s 1% 1% -

Đáng ngạc nhiên là vòng lặp for có thêm không gian là sự lựa chọn nhanh nhất ở đây!

Kết luận của tôi là vòng lặp while nên được sử dụng trên nền tảng x86_64 nếu lập trình viên đang tối ưu hóa tốc độ. Rõ ràng một vòng lặp for nên được sử dụng khi tối ưu hóa cho không gian. Kết quả của tôi không may là không kết luận về các nền tảng khác.


9
Kết luận là sai lầm trắng trợn. Benchmarkcó những hạn chế và không thể được sử dụng để phân biệt nhanh và chậm nếu kết quả nằm trong phạm vi 7% của nhau. Hơn nữa, bạn chưa kiểm tra sự khác biệt giữa các vòng lặp forwhilebởi vì mỗi phụ sẽ dietrước khi tự đi đến các vòng lặp. Và từ khi nào số lượng khoảng trắng quan trọng đối với trình thông dịch Perl? Xin lỗi, nhưng phân tích là vô cùng thiếu sót.
Zaid

2
@Zaid, Cảm ơn ý kiến ​​của bạn! Bạn có phiền đăng câu trả lời của riêng bạn để mọi người có thể học hỏi từ đó không? :) Có diemã trong mã của tôi vì ý định của tôi là chỉ kiểm tra chênh lệch thời gian biên dịch . Như những người khác đã chỉ ra mã byte kết quả là giống hệt nhau, do đó không có điểm nào trong việc kiểm tra điều đó. Đáng ngạc nhiên là số lượng khoảng trắng dường như tạo ra một sự khác biệt nhỏ trong trường hợp này trong môi trường thử nghiệm của tôi. Nó có thể có liên quan đến cách các nhân vật cuối cùng được sắp xếp trong bộ nhớ hoặc một cái gì đó tương tự ...
snap

4
Tôi không cần phải đăng câu trả lời vì những gì tôi muốn nói đã được đề cập bởi bdonlan. Và ngay cả khi bạn đang so sánh thời gian biên dịch, những con số không Benchmarkcó kết quả. Đừng tin vào sự khác biệt 1% nào cả!
Zaid

Chỉ 60 lần lặp? Chạy thử nghiệm trong khoảng 5 phút để có được thời gian tương đối chính xác hơn.
Vịt Mooing

-60chạy thử nghiệm trong 60 giây.
chụp

2

Về lý thuyết, một trình biên dịch hoàn toàn ngây thơ có thể lưu trữ chữ '1' theo nghĩa nhị phân (lãng phí dung lượng) và kiểm tra xem liệu 1 == 0 mỗi lần lặp (lãng phí thời gian và nhiều không gian hơn).

Tuy nhiên, trong thực tế, ngay cả khi tối ưu hóa "không", trình biên dịch vẫn sẽ giảm cả hai xuống như nhau. Họ cũng có thể phát ra cảnh báo vì nó có thể chỉ ra lỗi logic. Chẳng hạn, đối số whilecó thể được định nghĩa ở một nơi khác và bạn không nhận ra nó không đổi.


2

Tôi ngạc nhiên không ai đưa ra hình thức trực tiếp hơn, tương ứng với lắp ráp mong muốn:

forever:
     do stuff;
     goto forever;

Liều lượng không kết thúc với cùng mã máy như while 1 hoặc for (;;) trong c?
Copas

1
Một thiếu sót khác của cách tiếp cận đó: nó vi phạm đóng gói bằng cách không bao quanh vòng lặp trong một khối - do đó, bất kỳ biến nào được khai báo trong vòng lặp đều có sẵn bên ngoài vòng lặp. (Tất nhiên, bạn có thể { forever: do stuff; goto forever; })
Roy Tinker

2

while(1)là một thành ngữ for(;;)được hầu hết các trình biên dịch công nhận.

Tôi rất vui khi thấy rằng perl cũng nhận ra until(0).


Trong tình huống nào cho đến khi (0) có ích?
Copas

3
Until () ngược lại với while () giống như trừ khi () ngược lại với if (). Như được đề xuất ở mọi nơi trong chủ đề này, người ta có thể viết: do {Something ...} while (! Condition) Một sự thay thế có thể là cho đến khi (condition) {
Something

2

Để tóm tắt cuộc tranh luận for (;;)vs while (1)rõ ràng là trước đây nhanh hơn trong thời kỳ các trình biên dịch không tối ưu hóa cũ hơn, đó là lý do tại sao bạn có xu hướng nhìn thấy nó trong các cơ sở mã cũ hơn như bình luận mã nguồn Lions Unix, tuy nhiên trong thời đại tối ưu hóa xấu trình biên dịch những lợi ích đó được tối ưu hóa khớp nối mà với thực tế là cái sau dễ hiểu hơn cái trước tôi tin rằng nó sẽ thích hợp hơn.


2

Chỉ cần bắt gặp chủ đề này (mặc dù khá muộn vài năm).

Tôi nghĩ rằng tôi đã tìm thấy lý do thực tế tại sao "for (;;)" tốt hơn "while (1)".

theo "tiêu chuẩn mã hóa barr 2018"

Kernighan & Ritchie long ago recommended for (;;) , which has the additional benefit
of insuring against the visually-confusing defect of a while (l); referencing a variable l’.

về cơ bản, đây không phải là vấn đề tốc độ mà là vấn đề dễ đọc. Tùy thuộc vào phông chữ / bản in của mã, số một (1) trong một thời gian có thể trông giống như một chữ cái viết thường l.

tức là 1 vs l. (trong một số phông chữ trông giống hệt nhau).

Vì vậy, trong khi (1) có thể trông giống như một số vòng lặp while phụ thuộc vào chữ L biến.

while (true) cũng có thể hoạt động nhưng trong một số trường hợp C cũ và C nhúng thì true / false vẫn chưa được xác định trừ khi stdbool.h được bao gồm.


2
Tôi muốn nói rằng vấn đề trong mã của bạn sẽ là bạn có một biến có tên l, không phải 1lcó thể trông tương tự.
mjuopperi

Đồng ý, tôi biết tiêu chuẩn mã hóa Barr cũng nói ở nơi khác rằng các biến phải có ít nhất 3 ký tự ngay cả trong các vòng lặp. tức là không có i ++, vv trong một vòng lặp for. Tôi có xu hướng nghĩ rằng có thể là một chút mặc dù. Trong khi gõ tôi cũng nhận thấy không chỉ chữ L trông giống chữ 1. Chữ i thường được sử dụng làm biến cũng có thể gây ra sự cố.
Nick Law

-3

Tôi sẽ nghĩ rằng cả hai đều giống nhau về hiệu suất. Nhưng tôi thích trong khi (1) cho khả năng đọc nhưng tôi đặt câu hỏi tại sao bạn cần một vòng lặp vô hạn.


-14

Họ giống nhau. Có nhiều câu hỏi quan trọng hơn để suy ngẫm.


Quan điểm của tôi đã được ngụ ý nhưng không được thực hiện rõ ràng ở trên, đó là một trình biên dịch đàng hoàng sẽ tạo ra cùng một mã chính xác cho cả hai dạng vòng lặp. Điểm lớn hơn là cấu trúc lặp là một phần nhỏ trong thời gian chạy của bất kỳ thuật toán nào và trước tiên bạn phải đảm bảo rằng bạn đã tối ưu hóa thuật toán và mọi thứ khác liên quan đến nó. Tối ưu hóa cấu trúc vòng lặp của bạn hoàn toàn nên ở cuối danh sách ưu tiên của bạn.


22
Không có liên kết hoặc giải thích. Vô ích, chủ quan và một chút hạ mình.
cdmckay

1
cũng không có bằng chứng nhưng anh ấy đúng. Cả hai đều gọi Opcode để nhảy khi sai. (sẽ làm cho nó giống như goto nhưng không ai thích gotos)
Matthew Whited

3
Tôi đã không biết rằng chỉ có những câu hỏi quan trọng được hỏi, lỗi của tôi là câu hỏi đầu tiên của tôi.
Copas

3
Vâng, tôi thừa nhận nó đang hạ mình. Nhưng nghiêm túc, ngay cả khi không có bất kỳ bằng chứng nào, rõ ràng là họ sẽ ở trong cùng một sân bóng tốc độ; Nếu câu hỏi là về phong cách, sẽ có điều gì đó để tranh luận. Tôi đã cố gắng đưa ra quan điểm rằng trong danh sách những điều cần lo lắng, điều này thực sự nên ở cuối danh sách.
Đánh dấu tiền chuộc

8
Tôi đã không cố gắng để trở thành một kẻ ngốc. Tôi đã cố gắng để làm cho một điểm. Khi tôi đăng nó, tôi đã cố gắng cho một loại hài hước đen tối, và rõ ràng là tôi đã thất bại; cho rằng tôi xin lỗi.
Đánh dấu tiền chuộc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.