Xref: utzoo comp.lang.modula2:1235 comp.lang.c:15879 Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uflorida!novavax!twwells!bill From: bill@twwells.uucp (T. William Wells) Newsgroups: comp.lang.modula2,comp.lang.c Subject: variable limits (was Re: "for" loops) Message-ID: <350@twwells.uucp> Date: 30 Jan 89 06:31:19 GMT References: <19579@agate.BERKELEY.EDU> <8515@lanl.gov> <6419@polya.Stanford.EDU> Reply-To: bill@twwells.UUCP (T. William Wells) Organization: None, Ft. Lauderdale Lines: 71 Summary: Expires: Sender: Followup-To: Distribution: Keywords: [This may be a repost. Sorry if so.] In article <6419@polya.Stanford.EDU> crew@Polya.Stanford.EDU (Roger Crew) writes: : Here's a quiz: : How would you write the following in C? : : VAR a, b, c : Char; : ... : FOR c = a TO b DO ... END; : : You can even assume that the body of the loop affects neither a nor b. : Hint: the answer is *not* : : char a, b, c; : ... : for (c = a; c <= b; ++c) { ... } No, you write it: int a, b, c; /* or char a,b; int c; */ ... for (c = a; c <= b; ++c) { ... } It is, in general, a bad practice to use a char as an iteration control variable. This example does, however, point up something that must be dealt with in any language: each variable has limiting points where its behavior becomes unreliable. (Even languages that allow unbounded precision have this problem, though their limits are usually ridiculously large.) At those limits, one must take special care to avoid passing them. For integral types in C, the limits are: char 0..127 0..2**7-1 signed char -127..127 (ANSI C signed char) -2**7+1..2**7-1 short -32767..32767 -2**15+1..2**15-1 int -32767..32767 -2**15+1..2**15-1 long -2147483647..2147483647 -2**31+1..2**31-1 unsigned char 0..255 0..2**8-1 short 0..65535 0..2**16-1 int 0..65535 0..2**16-1 long 0..4294967295 0..2**32-1 Any time your values might get even close to these limits you need to examine the code to see if there is a possibility that something overflows. Of course, this problem is not restricted to integers. Floats have this problem too, not to mention their problems with precision. Pointers into objects also have this kind of problem. Consider this nonportable code: for (p = &array[limit]; --p >= array; ) { ... } Since p will point before array at the last iteration, this may fail. To give a concrete example, consider a machine with a data address space that starts at zero (e.g., any machine with split I&D, like a PDP-11 or an 8086), and an array whose element size is n and which is stored at address m < n. When p decrements past the start of array, its new value is unlikely to be m - n, a negative number. Since the address computation is likely to be done unsigned (as long as sizeof(int) == sizeof(pointer), anyway), the actual value is the unsigned version of m - n, a very large number and in any case, not less than array. So the loop never terminates. (Yes, Chris, I remember!) --- Bill { uunet!proxftl | novavax } !twwells!bill