convert ubyte[k..k + 1] to int

Andrew Wiley wiley.andrew.j at gmail.com
Wed May 16 21:15:38 PDT 2012


On Wed, May 16, 2012 at 11:07 PM, H. S. Teoh <hsteoh at quickfur.ath.cx> wrote:

> On Wed, May 16, 2012 at 10:25:51PM -0500, Andrew Wiley wrote:
> > On Wed, May 16, 2012 at 11:03 AM, Regan Heath <regan at netmail.co.nz>
> wrote:
> >
> > > On Wed, 16 May 2012 15:24:33 +0100, ref2401 <refactor24 at gmail.com>
> wrote:
> > >
> > >  i have an array of ubytes. how can i convert two adjacent ubytes from
> the
> > >> array to an integer?
> > >>
> > >> pseudocode example:
> > >> ubyte[5] array = createArray();
> > >> int value = array[2..3];
> > >>
> > >> is there any 'memcpy' method or something else to do this?
> > >>
> > >
> > > You don't need to "copy" the data, just tell the compiler to "pretend"
> > > it's a short (in this case, for 2 bytes) then copy the value/assign to
> an
> > > int. e.g.
> > >
> > > import std.stdio;
> > >
> > > void main()
> > > {
> > >        ubyte[5] array = [ 0xFF, 0xFF, 0x01, 0x00, 0xFF ];
> > >        int value = *cast(short*)array[2..3].ptr;
> > >        writefln("Result = %s", value);
> > > }
> > >
> > > The line:
> > >  int value = *cast(short*)array[2..3].ptr;
> > >
> > > 1. slices 2 bytes from the array.
> > > 2. obtains the ptr to them
> > > 3. casts the ptr to short*
> > > 4. copies the value pointed at by the short* ptr to an int
> > >
> > > You may need to worry about little/big endian issues, see:
> > > http://en.wikipedia.org/wiki/**Endianness<
> http://en.wikipedia.org/wiki/Endianness>
> > >
> > > The above code outputs "Result = 1" on my little-endian x86 desktop
> > > machine but would output "Result = 256" on a big-endian machine.
> > >
> > > R
> > >
> > >
> > Unfortunately, this is undefined behavior because you're breaking
> > alignment rules. On x86, this will just cause a slow load from memory.
> > On ARM, this will either crash your program with a bus error on newer
> > hardware or give you a gibberish value on ARMv6 and older.
> > Declaring a short, getting a pointer to it, and casting that pointer
> > to a ubyte* to copy into it is fine, but casting a ubyte* to a short*
> > will cause a 2-byte load from a 1-byte aligned address, which leads
> > down the yellow brick road to pain.
>
> Do unions suffer from this problem? Could this prevent alignment
> problems:
>
>        short bytesToShort(ubyte[] b)
>        in { assert(b.length==2); }
>        body {
>                union U {
>                        short val;
>                        ubyte[2] b;
>                }
>                U u;
>
>                u.b[] = b[];
>                return u.val;
>        }
>
> ?
>
>
As I understand it, this should be fine because the compiler will guarantee
that the union is aligned to the maximum alignment required by one of its
members, which is the short. This is probably the safest solution.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20120516/01367ede/attachment-0001.html>


More information about the Digitalmars-d-learn mailing list