Xref: news2.mv.net comp.os.msdos.djgpp:2958 From: alexlehm AT rbg DOT informatik DOT th-darmstadt DOT de (Alexander Lehmann) Newsgroups: comp.os.msdos.djgpp Subject: Re: LONG_MIN question Date: 22 Apr 1996 15:47:15 GMT Organization: Technische Hochschule Darmstadt Lines: 83 Message-ID: <4lg9m3$1cod@rs18.hrz.th-darmstadt.de> References: <01I3RZ7ZOPMQ005280 AT cc DOT uab DOT es> NNTP-Posting-Host: hp62.rbg.informatik.th-darmstadt.de To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp x DOT pons AT cc DOT uab DOT es (ILGES AT cc DOT uab DOT es) wrote: : Dear programmers, : If I write a sentence like this: : if (0L < -2147483647L) ^ don't you mean 2147483648L? : ..... : the result is TRUE, although it should not be. In fact, DJGPP warns it : when compiling: : "warning: decimal constant is so large that it is unsigned" : It is possible to do the right comparison by writing : if (0L < LONG_MIN) : ..... : LONG_MIN is defined in as: : #define LONG_MIN (-2147483647L-1L) : I suppose this makes the code a bit slower. I'd like to know: : 1-Is there some way to avoid this subtraction each time I compare a value : and -2147483648L : 2-Why this problem exists? Why doing (-2147483647L-1L) does not produce : the same problem? : 3-Why DJGPP defines : #define SHRT_MIN (-32768) : and BC++4.52 defines : #define SHRT_MIN (-32767-1) : even for 32 bit applications? The problem with -2**31 is a rather bizarre feature of the type promotion rules in ANSI. The language syntax definition doesn't define negative number literals, rather the negative numbers are generated by the unary - operator. This I think is to make an expression like: 2-1 easier to parse, other languages (e.g. Prolog) consider the -1 to be one token and report a syntax error, so you have to write 2- 1. So an expression like 0 < -2147483648L is parsed as (0) < (-(2147483648L)). Now unsigned constants are (I think) int until they are larger than MAX_INT, then unsigned int, then long, then unsigned long (since in gcc sizeof(int)==sizeof(long), the int part doesn't really happen, but 16 bit int compilers do that). The constant (2147483648L) is too large to fit into a signed long, so it is considered an unsigned long (even though there is a L). Now the unary - operation is defined on unsigned numbers as well as on signed ones, so the constant remains unsigned even after that. Negating the number doesn't work (neither as signed nor as unsigned) since the 2s complement of the number is the number again. The reason why it works when doing (-2147483647L-1L) instead is that then both constants are signed longs and the result fits into a signed long as well. Note that this doesn't actually create a subtraction operation in the resulting assembler code (at least with optimisation turned on) (You may not even get the if conditional calculated, since it is constant at compile time, gcc is pretty smart with respect to evaluating constant sub- expressions). (I would include a sample asm code piece here, but I am writing this on a hppa risc machine and the code is pretty unreadable). Another possibility to get the constant is to do an explicit cast to long, this way, the constant is signed ((long)(-2147483648)). As for the 3rd question, I'm not sure what the ANSI spec says about the type of the *_MIN/*_MAX constants, I think the smallest type constants are usually represented in is int, so if int is 16 bits wide, the first definition may cause the same problem as LONG_MIN, with 32 bit ints it works anyway. So if they have a definition that works with both modes, they can use that one and don't have to clobber up their headers with additional #ifdefs. (I would expect that bc has similar optimizations for evaluating constant expressions as gcc). BTW: I have no idea if bcc in 32 bit mode has 32 bit ints (I think the mode is called 32 bit because of the address space), but I guess it would be a good idea. bye, Alexander -- Alexander Lehmann, | "On the Internet, alex AT hal DOT rhein-main DOT de (plain, MIME, NeXT) | nobody knows alexlehm AT rbg DOT informatik DOT th-darmstadt DOT de (plain) | you're a dog."