10

Recently I found this article that claims that the idea to prefer for(;;) over while(1) for infinite loop came because the C compiler originally available on PDP-11 generated an extra machine instruction for while(1).

Btw now even Visual C++ warnings tend to favor the former.

How realistic is such attribution of for(;;) idiom?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 2
    There is no such thing as `true` in C... – fredoverflow Nov 28 '11 at 08:36
  • Poor article. He sets out to prove that exception handling doesn't cost anything and then tests that assertion with code that doesn't throw any exceptions. Borland have a far better paper on the same topic. – user207421 Nov 28 '11 at 08:56
  • 2
    @FredOverflow: Incorrect. `true` is a macro that is defined in `stdbool.h` (C99 standard, section 7.16) – JeremyP Nov 28 '11 at 10:13
  • 5
    @JeremyP: more accurate would have been to say, "at the time you're talking about, there was no such thing as `true` in C". – Steve Jessop Nov 28 '11 at 10:26
  • 1
    Ok guys, we all know the usual `for(;;)` vs `while(1)` routine. But now I am genuinely curious if anyone can come up with a good hystorical quote for the PDP-11 factoid. – hugomg Nov 28 '11 at 12:44
  • 3
    @EJP: The point of the article is that adding try/catch blocks has essentially zero cost for those cases where no exception is thrown, and this is made quite clear in the article (e.g. "catch code (never executed)", "A decision was made [by Microsoft] to implement an exception mechanism that imposes as close to zero as possible cost during normal execution, but is in fact fairly expensive when an exception is actually thrown."). A program that throws exceptions often enough to be worried about the cost of dispatching those exceptions is using exceptions the wrong way. – Martin B Nov 28 '11 at 13:05

6 Answers6

10

The "for(;;)" idiom is explicitly mentioned in the original K&R. That's attribution enough for me :)

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • 2
    Keep in mind that K&R wrote the PDP-11 compiler, which was the working prototype that led to the book… – Potatoswatter Nov 28 '11 at 07:49
  • 2
    It explicitly mentions `for(;;)`, but not the PDP-11 or anything about generated code. It just says that if the condition is omitted, it's always assumed to be true. – Jerry Coffin Nov 28 '11 at 10:09
  • @Potatoswatter: R wrote the PDP-11 compiler, K didn't. He was busy with other bits of Unix at the time. – Steve Jessop Nov 28 '11 at 10:32
  • -1. The appearance of `for(;;)` in K&R1 does not prove the idiom's origin in the PDP-11 machine language in any way. – Fred Foo Nov 28 '11 at 12:51
7

Beware to certain "sensible attribution", because are often sources of false mith, due to lack of context. The OP tagged the message both C and C++.

Now, K&R can be semi-gods about C history, but certainly cannot be considered authority about C++. Furthermore, compiler optimization can play a fundamental role in C++, but is often viewed as "abusive" from C system programmers (they like to see C as "Assembler with expressions", rather than a "high level language").

Todays compilers will produce much likely exactly the same code (this can be easily proven), and the use of one or the other is much more a matter of taste, then other.

In this sense, I tend to favor for(;;) because I can easily read it as "for-ever" while while(true) read as "while this true thing is true", making you to figure how if it can even be false ... . 2 msecs of brain wasted! (But it's a personal opinion: I know many people that has to think more about for(;;) than while(true))

However, I can also recognize both of them as "pictorial representation" (without actually read the text, just looking how they look via photographic memory) pointing to a same intellectual concept (stay here until someone will kick you away from the inside).

About the MS warning, sometime it saves you from bad-written expressions (like true||a). But is clearly abused, and should not appear, for trivial expressions with no operation inside. Nerveless, MS compiler produce the same machine code in both the cases. May be feedbacks to MS will make them less tedious about that warning on future releases.

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
  • 9
    You can be extra cool and add `#define ever (;;)`. Then you can write literally `for ever`. – rodrigo Nov 28 '11 at 09:36
  • 1
    @rodrigo: +1 for irony. But I don't suggest it. If I see 'for ever' I wonder WTF 'ever' may hide (especially if it is hidden in 50 depth include files). 'for(;;)' is just what the language is. More "secure" to anyone. – Emilio Garavaglia Nov 28 '11 at 10:30
  • @rodrigo: for that matter, you can `#define universe_exists (true)`. – Steve Jessop Nov 28 '11 at 10:34
  • 4
    I was joking, of course. Any sane C programmer would write `#define EVER (;;)`, but `for EVER` doesn't look so nice [joking again]. – rodrigo Nov 28 '11 at 11:21
  • 7
    Just `#define forever` and let it be `for (;;)` on odd weeks and `while (1)` on even. – u0b34a0f6ae Nov 28 '11 at 11:41
  • @rodrigo brilliant! im surprised nobody wrote a language with this as a keyword. – Dmytro Nov 09 '16 at 00:55
6

Here's what the V7 Unix compiler cc produces (using SIMH and an image from TUHS):

$ cat>a.c
main(){
 while(1);
}
$ cat>b.c
main(){
 for(;;);
}
$ cc -S a.c
$ cc -S b.c

a.c (while) compiles to:

.globl  _main
.text
_main:
~~main:
jsr     r5,csv
jbr     L1
L2:L4:tst       $1
jeq     L5
jbr     L4
L5:L3:jmp       cret
L1:jbr  L2
.globl
.data

While b.c (for) becomes:

.globl  _main
.text
_main:
~~main:
jsr     r5,csv
jbr     L1
L2:L4:jbr       L4
L5:L3:jmp       cret
L1:jbr  L2
.globl
.data

So it's at least true that for(;;) compiled to fewer instructions when not using optimization. However, when compiling with -O, both programs produce exactly the same assembly:

.globl  _main
.text
_main:
~~main:
jsr     r5,csv
L4:jbr  L4
.globl
.data

and when I add a loop body of printf("Hello");, the programs are still the same.

So, it might be that the idiom has its origins in PDP-11 machine language, but by 1979 the difference was already largely irrelevant.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
1

I don't know if it is true, but the article claim is sensible and realistic. And for(;;) is shorter to type than while(1)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    Actually, it's not. Even though `while(1)` has more characters, `for(;;)` requires you to press the same button twice which can really slow typing down. – orlp Nov 28 '11 at 10:31
  • 11
    As well as being shorter to type, it avoids all-important wear and tear on the `e` and `l` keys, shifting it over to `;`. This prolongs the useful life of the keyboard. – Steve Jessop Nov 28 '11 at 10:36
  • 3
    @Steve: Hw inteesting! I need t peseve all the lettes I have let. – Potatoswatter Nov 28 '11 at 11:21
  • 1
    By the time you've read this whole thread trying to decide which one to use, you'll probably have wasted more time than you ever would have gained by typing the faster one for the rest of your life. – mk12 Aug 14 '12 at 21:15
-1

Um. Think you will find that K&R didn't write the PDP-11 compiler as the PDP-11 was a 'machine' (not a language) which already had its own MACRO Assembler for its own PDP-11 instruction set.

K&R {reputedly) wrote their own 'C' compiler in ... well.. if would have to have been MACRO wouldn't it (as that was the only instruction set Assembler available on the PDP) and then (reputedly) wrote Unix in 'C' as they thought they could do better than DEC's PDP-11 Operating Systems (RT-11 and RSTS-11) .. and they were probably right!

Richard
  • 79
  • 1
  • 1
  • 1
    If you don't want to guess, you can read Dennis Ritchie's own description of what happened in [The Development of the C Language](http://cm.bell-labs.com/cm/cs/who/dmr/chist.html). – Bo Persson Dec 28 '12 at 20:03
-4

for(;;) is idiomatic so it's great if your code will only ever be read by experienced C programmers. while(true) will be more understandable to inexperienced programmers and non C programmers. The former also relies on some non obvious behaviour, namely that an empty boolean expression evaluates to true. For these reason, if you must pick one, I would say go for the latter.

However I would argue that in virtually all real cases, the programmer doesn't really want the code to loop forever. There is always a reason why you might want the loop to terminate, even if it's just that the user has hit control-C. There's never a need for an infinite loop.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • 7
    If you're programming a machine that ideally never stops, and C is used to program many such machines, then an infinite loop is the perfect model. – Potatoswatter Nov 28 '11 at 11:22
  • 1
    What you write is true, but it does not address the history at all, which is what is this question about. – Suma Nov 28 '11 at 13:02
  • @Suma: But the question as strictly specified wasn't about programming, it was about the history of C. – JeremyP Nov 28 '11 at 13:51
  • @Potatoswatter: there is no such machine. There is always the possibility that the machine needs to be taken offline for maintenance or to be thrown away. – JeremyP Nov 28 '11 at 13:53
  • 1
    Going offline for maintenance doesn't necessarily mean exiting the main loop. Such a machine already has a catch-all for fault conditions, which is to reboot automatically if an internal watchdog timer isn't reset. The best way to install an update is to activate that well-tested code path, using the same well-tested command dispatch system as does everything else in the main loop. – Potatoswatter Nov 28 '11 at 14:10
  • 1
    Also, since this is C++, you can also exit a loop by an exception, which is more elegant than adding a global `is_exiting` condition and plays well with what I just mentioned. – Potatoswatter Nov 28 '11 at 14:11
  • @Potatoswatter: Exiting a loop by an exception is a horrible idea unless an exceptional condition has actually occurred. Normal shutdown is not an exceptional condition. It is far better to declare what your loop exit condition is in the place where it is most easily found - i.e. in the loop condition - than to hide it somewhere in the loop's body. – JeremyP Nov 28 '11 at 14:24
  • 2
    For a machine which is programmed to never stop, stopping to install an update is *always* an exceptional condition. Returning from `main` will be defined to cause an exception and a hard reboot just like any other reasonable alternative. Anyway… I guess you have to see it to believe it. It's a big world out there. – Potatoswatter Nov 28 '11 at 14:34
  • 1
    the HOWEVER part is religion, not programming. Loops can also be exited by break. Programmers knows that, hence for(;;) does not mean "infinite", just "not yet known at loop entrance, and not related to an expression evaluation of a state variable". – Emilio Garavaglia Nov 28 '11 at 15:00
  • I imagine this has been voted down so much because it does not address the question. However, "while(true) will be more understandable to inexperienced programmers" is a good and useful point. – MickeyfAgain_BeforeExitOfSO Nov 14 '17 at 15:18