Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!husc6!ut-sally!utah-cs!donn From: donn@utah-cs.UUCP Newsgroups: comp.lang.c++,comp.lang.c Subject: Re: bug re unsigned to signed conversion? Message-ID: <4605@utah-cs.UUCP> Date: Thu, 28-May-87 06:28:46 EDT Article-I.D.: utah-cs.4605 Posted: Thu May 28 06:28:46 1987 Date-Received: Sat, 30-May-87 01:17:34 EDT References: <4626@columbia.UUCP> Organization: University of Utah CS Dept Lines: 76 Xref: utgpu comp.lang.c++:263 comp.lang.c:2141 Summary: the C compiler is right, the C++ compiler is wrong David Eppstein says that he expects no output from the following program: ------------------------------------------------------------------------ #include int a = -1; unsigned b = 2; inline int conv() { return b; } main() { if (a > b) cout << "(int) -1 > (unsigned) 2 ???\n"; if (a > conv()) cout << "(int) -1 > (int) (unsigned) 2 ????????\n"; } ------------------------------------------------------------------------ I believe both C and C++ apply the same rules for automatic conversions in this example. The first test 'a > b' should produce 1 since 'a' is converted to unsigned and on a two's complement machine, '(unsigned) -1' is the largest unsigned integer. In the second test 'a > conv()', both operands are signed integers and hence the comparison is a signed comparison and the result is 0. C++ 1.2.1 cfront fails to generate a C cast to coerce the type of the return value of conv() to int; the C++ reference manual (r.8.1) guarantees that an inline function has the same result as a call to a real function, rather than a call to a macro, so C++ 1.2.1 is wrong. (This reminds me of some bugs with Fortran statement functions and the 4.2 BSD f77 compiler...) It is probably useful to note here that the 4.3 BSD C compiler is an 'unsigned preserving' compiler in the terms of ANSI C -- unsigned char and unsigned short promote to unsigned int in implicit conversions. C++ is explicitly 'value preserving' -- small unsigned types promote to int (r.6.6, except unsigned short conversion is not treated; in any case a qualification about unsigned short on machines where sizeof (unsigned short) == sizeof (int) is needed). Since C++ 1.2.1 cfront makes no effort to force its 'value preserving' practice on 'unsigned preserving' Unix C compilers, it is thus the case that on Unix machines, C++ is also 'unsigned preserving'. Donn Seeley University of Utah CS Dept donn@cs.utah.edu 40 46' 6"N 111 50' 34"W (801) 581-5668 utah-cs!donn PS -- Personal opinion: the argument for 'value preserving' promotion is that it is less confusing -- it is somehow safer for the novice to be able to write: int i = -1; unsigned char uc = 2; unsigned int ui = 2; if (uc > i) printf("ANSI\n"); if (ui < i) printf("ANSI too\n"); I fail to see how this is less confusing... PPS -- C++ 1.2.1 cfront botches certain constant comparisons between int and unsigned; for example, the following program prints 'wrong': ------------------------------------------------------------------------ #include int main() { if ((unsigned) 2 > -1) cout << "wrong\n"; return 1; } ------------------------------------------------------------------------ If the cast is moved to the right operand of > in the example, C++ 1.2.1 cfront simply punts on the constant folding and lets the C compiler handle it.