From mboxrd@z Thu Jan 1 00:00:00 1970 To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net> In-reply-to: Your message of "Wed, 16 Jun 2010 11:11:09 +0200." References: From: Bakul Shah Date: Wed, 16 Jun 2010 10:52:10 -0700 Message-Id: <20100616175211.106945B2E@mail.bitblocks.com> Subject: Re: [9fans] portability question Topicbox-Message-UUID: 346036d8-ead6-11e9-9d60-3106f5b1d025 On Wed, 16 Jun 2010 11:11:09 +0200 hugo rivera wrote: > Can someone clarify why the program included outputs 'AB000000' (as I > expect) on 32 bit systems and 'FFFFFFFFAB000000' on 64 bit systems? > where all those 1's came from? what's the portable way of doing this? > sorry for newbie questions like this. > > > unsigned long l; > unsigned char c; > > l = 0L; > c = 0xAB; > l |= c << 24; > printf("%lX\n", l); For use of C on non-plan9 machines I would recommend downloading the last draft of the C9x standard as a ready reference. Google for n843. As per Section 6.5.7 of C9x, both operands of << must be of "integer type" and the result type is that of the left operand. Since sizeof c < sizeof(int), it is promoted. Now 6.3.1.2 says "if an int can represent all values of the original type, the value is converted to an int". So c is first converted to an int which means c << 24 is an integer and -ve. Since an int is smaller than a long (in your case) it is promoted to a long. Changing the |= statement to l |= (unsigned)c << 24; should give you what you want.