digitalmars.D.bugs - Typedef bit twiddling
- Sam McCall (8/8) Jul 27 2004 If i'm being stupid please slap me.
- Arcane Jill (37/44) Jul 27 2004 Sounds like a bug to me. One thing though - maybe Walter could clarify -...
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
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








Arcane Jill <Arcane_member pathlink.com>