From owner-freebsd-current Mon Nov 11 6: 0:33 2002 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8AE8C37B401 for ; Mon, 11 Nov 2002 06:00:29 -0800 (PST) Received: from dignus.com (sdsl-64-32-254-102.dsl.iad.megapath.net [64.32.254.102]) by mx1.FreeBSD.org (Postfix) with ESMTP id 92A3B43E6E for ; Mon, 11 Nov 2002 06:00:28 -0800 (PST) (envelope-from rivers@dignus.com) Received: from lakes.dignus.com (lakes.dignus.com [10.0.0.3]) by dignus.com (8.11.6/8.11.3) with ESMTP id gABDmQR16141; Mon, 11 Nov 2002 08:48:26 -0500 (EST) (envelope-from rivers@dignus.com) Received: (from rivers@localhost) by lakes.dignus.com (8.11.6/8.11.3) id gABDt2g55397; Mon, 11 Nov 2002 08:55:02 -0500 (EST) (envelope-from rivers) Date: Mon, 11 Nov 2002 08:55:02 -0500 (EST) From: Thomas David Rivers Message-Id: <200211111355.gABDt2g55397@lakes.dignus.com> To: FreeBSD-current@FreeBSD.ORG, yoshint@flab.fujitsu.co.jp Subject: Re: gcc 3.2.1 optimization bug ? In-Reply-To: Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG > > For the source code below, compiling gcc -O2/-O3 seem to produce > incorrect code. > > ----------------------------------- > #include > int main(int argc, char* argv[]) > { > unsigned int x = 0x12345678; > unsigned short tmp; > printf("%x\n", x); > tmp = ((unsigned short *)&x)[0]; > ((unsigned short *)&x)[0] = ((unsigned short *)&x)[1]; > ((unsigned short *)&x)[1] = tmp; > printf("%x\n", x); > return 0; > } > ----------------------------------- > > Several people have pointed out that using "volatile" will help with your code. But - even with the use of "volatile" - your code is invalid ANSI C. You are doing something called "type punning" - which is illegal. Basically, you can't reference a datum via a different type and expect it to do anything meaningful. When you take &x, you have and (unsigned int *) type. When you then cast that to an (unsigned short *) and then dereference it, you are referencing the datum 'x' via a different type. (consider, for example, a situation where `unsigned short' had the same alignment requirements as `unsigned int', your example would not address what you were thinking...) The C99 standard relaxed this rule somewhat, allowing (char *) pointers to be used to reference any datum. So, you could use memcpy() to accomplish what you're looking for, as in: unsigned short array[2]; memcpy(array, &x, sizeof(array)); but - while valid, that also suffers from several issues... Your code appears to simply want to swap the two (assumed) words in an integer. That could be accomplished with shifts, etc... This code makes all kinds of assumptions about the size of `int' and `short' - but represents an alternative approach: unsigned int t; unsigned int x; t = (x & 0xffff) << 16; x >>= 16; x |= t; Assuming `int' was 32-bits wide - this, or something similar, might be a more portable approach. - Dave Rivers - -- rivers@dignus.com Work: (919) 676-0847 Get your mainframe programming tools at http://www.dignus.com To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message