From: Jack Klein Newsgroups: comp.os.msdos.djgpp Subject: Re: GCC 2.95.3 and C standard(s) + commandline switch problems Message-ID: References: <4830 DOT 986817066 AT www1 DOT gmx DOT net> X-Newsreader: Forte Agent 1.8/32.548 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Lines: 116 Date: Tue, 10 Apr 2001 04:16:56 GMT NNTP-Posting-Host: 12.75.153.87 X-Complaints-To: abuse AT worldnet DOT att DOT net X-Trace: bgtnsc07-news.ops.worldnet.att.net 986876216 12.75.153.87 (Tue, 10 Apr 2001 04:16:56 GMT) NNTP-Posting-Date: Tue, 10 Apr 2001 04:16:56 GMT Organization: AT&T Worldnet To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com On Mon, 9 Apr 2001 13:51:06 +0200 (MEST), ahelm AT gmx DOT net wrote in comp.os.msdos.djgpp: > Hi > I'm having troubles with a subtle ANSI C standard problem > and maybe some bugs in the DJGPP port of GCC (commandline switches). > > What type is the result of the multiplication of two unsigned short > variables? There are exactly three possibilities: 1. unsigned int if USHRT_MAX > INT_MAX, as both unsigned shorts are converted to unsigned ints prior to the multiplication. This was and still is the case on many compilers for 8 and 16 bit processors, where short and int share the same 16 bit representation. 2. signed int if USHRT_MAX < INT_MAX, as both unsigned shorts are converted to signed ints prior to the multiplication. This is the case on many common compilers for 32 bit platforms where int has 32 bits and short 16 bits, including x86 gcc. 3. undefined if USHRT_MAX < INT_MAX < USHRT_MAX * USHRT_MAX and the product of the two unsigned shorts is greater than INT_MAX, as both unsigned shorts are converted to signed ints prior to the multiplication and arithmetic overflow of signed integer types results in undefined behavior. > The problem is that there is a difference between old and new ANSI > standard. No, there is not. > ANSI C (both standards) clearly state that the result of a binary > arithmetic operation is of the same type as the inputs after > applying the "usual arithmetic conversions" (to the inputs) when > necessary. > > Following the rules in 6.2.1.5 in the old standard > (usual arithmetic conversions), none of the rules apply > until reaching the last: > "Otherwise both operands have type int" You are missing the application of the fourth paragraph at the first level of indentation under 6.2.1.5: Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands: The result of the integer promotion rules is never anything smaller than an int. The integer promotion rules themselves are described in 6.2.1.1. in C90 and 6.3.1.1 in C99. > So both operands are converted to int before multiplication. > That explains the int (32bit) result of a 16x16bit multiplication > when using GCC. Because actually > (16bit -> 32bit) x (16bit -> 32bit) = 32bit > is computed > > The new standard however has a new rule in the "Ususal > arithmetic conversions": > > "If both operands have the same type, then no further conversion > is needed." Yes, but this immediately follows the paragraph: Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands: In fact this text is cut and pasted from a formatted copy of C99 that I have, but the wording is exactly identical to C89/C90. > And 6.2.5 (new standard) or 6.1.2.5 (old standard): ^^^^^^^ ITYM 6.2.1.5 again here. > "A computation involving unsigned operands can never overflow, > because a result that cannot be represented by the resulting > unsigned integer type is reduced modulo the number that is > one greater than the largest value that can be represented > by the resulting type." > > This clearly defines the overflow behaviour of unsigned > operations. [snip] There are very, very few things that you can do in C with an object of a type smaller than int without promoting it to int in the process. Prior to C89 and function prototypes you could assign a type smaller than int to another type also smaller than int, the same or a different type. While this might require a conversion, it would not necessarily be a conversion "all the way" to int. With the advent of function prototypes you can also pass a type smaller than int to a function or return a type smaller than int from a function that is so prototyped. In any arithmetic, bit-wise, shift, or logical expression containing the value of an object smaller than int, this value is promoted to at least signed or unsigned int per the promotion rules. Specifically in the abstract machine no operator other than sizeof is ever applied to a value of a type smaller than int. Of course the implementation can sometimes optimize the actual conversion away under the as-if rule. [posted & mailed] -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq