www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Typedef bit twiddling

reply Sam McCall <tunah tunah.net> writes:
If i'm being stupid please slap me.

public static final uint UINT= (cast(uint)(-1)) >>> 2;
printf("%x\n",UINT); // 0x3fffffff, as expected

typedef uint foo;
public static final foo FOO= (cast(foo)(-1)) >>> 2;
printf("%x\n",FOO); // 0xffffffff !

DMD 0.96 on Linux.

Sam
Jul 27 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <ce568c$212e$1 digitaldaemon.com>, Sam McCall says...
If i'm being stupid please slap me.

public static final uint UINT= (cast(uint)(-1)) >>> 2;
printf("%x\n",UINT); // 0x3fffffff, as expected

typedef uint foo;
public static final foo FOO= (cast(foo)(-1)) >>> 2;
printf("%x\n",FOO); // 0xffffffff !

DMD 0.96 on Linux.
Sounds like a bug to me. One thing though - maybe Walter could clarify - I've never entirely understood why D has the ">>>" operator at all. It seems to me that ">>" would suffice. Java has two separate operators - but only because Java doesn't have unsigned types. Assembler has two separate types of shift instruction - but only because assembler registers and memory locations can be regarded as either signed or unsigned. But D, like C and C++, has both signed and unsigned types. It doesn't need ">>>". Just ">>", on its own, can do both jobs - it should simply be overloaded differently depending on whether its arguments are signed or unsigned, like C++ does. Compare D behavior (according to the documentation - I haven't tried this) with C behavior. The manual says "<< is a left shift. >> is a signed right shift. >>> is an unsigned right shift." This gives us the following. Here, assume u is unsigned and s is signed: Expression C/C++ D ~~~~~~~~~~ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ u >>> 3 (not defined) u / 8 s >>> 3 (not defined) ((uint)s) / 8 u >> 3 u / 8 ((int)u) / 8 s >> 3 s / 8 s / 8 The usefulness of (s >>> n) and (u >> n) seems highly questionable to me. Certainly not useful enough to warrant an extra operator, since if you really need to do this sort of thing, you can do it anyway with casting. These operators, incidently, gave me something of a headache when implementing them for the big integer class: Int. My Int class is signed, and a negative Int is (conceptually) preceeded by an infinite number of leading 1 bits. How can you unsigned shift right such a beast by (say) three bits? It makes no sense. (And yet, I had to overload >>> anyway, so that Int behaves like int, for use in templates). When I have argued that C got it wrong in the past (operator precedence, for example), Walter has always argued that compatibility with C was more important, because people are used to it. This being the case, the documented D behaviour of (u >> 3) is just too weirdly different from C to justify existence. I would suggest ditching >>> unless there's a /very/ good reason for it, and sticking with the expected C behavior. Maybe then your bug would just go away (although it sounds weirdly unrelated). Arcane Jill
Jul 27 2004