6 ms·
The important thing from a performance standpoint is to be able to hoist bounds checks out of inner loops. This avoids a check on each iteration. Languages whic
by Animats 3mo ago
The important thing from a performance standpoint is to be able to hoist bounds checks out of inner loops.
This avoids a check on each iteration.
Languages which have constructs such as
for foo in bartab {}
can usually hoist checks out of inner loops almost for free.
I used to argue with the C++ committee about to when it's OK to catch an error early.
If you write
#define LEN 1000
int tab[LEN];
for (auto p = tab; p++; p <= LEN) { *p = 0; }
that's a buffer overflow. The question is, is the compiler allowed to generate checking code which will abort the program before entering the loop? Or does it have to execute all the iterations up to the subscript error?
I argued that it's legit to catch an error at the point it becomes inevitable.
This leads to bikeshedding objections: "But what if a signal interrupts the loop before it runs off the end". That's why you need a language where undefined behavior has been nailed down to do this optimization properly.
- deleted 3mo ago[deleted]
- inigyou 3mo ago#define LEN 1000 int tab[LEN]; for (auto p = tab; p++; p <= tab+LEN) { if(*p == 42) foo(); *p = 0; } Not shown in frame: foo() calls exit(0) and tab always contains a 42. The current standard allows the compiler to hoist unsafety only if there's no possibility of I/O or volatile memory access. This is the reason for the rule that infinite loops without the above are undefined behavior - it allows the compiler to merge two loops, the second of which might crash and the first of which can't be proven to terminate.
- Animats 3mo agoRight, tab+LEN. The intended error was "<=" instead of "<".