Thread overview
correct way to split int into bytes?
Dec 01, 2004
newbie
Dec 01, 2004
Ben Hinkle
Dec 01, 2004
Thomas Kuehne
Dec 01, 2004
newbie
Dec 01, 2004
Thomas Kuehne
fastest way to split int into bytes?
Dec 01, 2004
newbie
Dec 01, 2004
Dr.Dizel
Dec 01, 2004
Thomas Kuehne
December 01, 2004
Without bit shifting, what's the correct way to split a int (32-bits) into 4 bytes?  BTW, I don't care about the byte order:

union U {
int i;
struct { byte a, b, c, d; }
}

U u;

void splitInt32( int x ) {
u.i = x;

// use the bytes ...
anotherFunc( u.a, u.b, u.c, u.d );

}

Will this code work with DMD and GDC?  And does the D language specification guarantee this code will always work, so I don't have to worry about every other potential compiler implementations in the future?

Thanks.


December 01, 2004
<newbie@d.com> wrote in message news:col0rk$1kj$1@digitaldaemon.com...
> Without bit shifting, what's the correct way to split a int (32-bits) into
4
> bytes?  BTW, I don't care about the byte order:
>
> union U {
> int i;
> struct { byte a, b, c, d; }
> }
>
> U u;
>
> void splitInt32( int x ) {
> u.i = x;
>
> // use the bytes ...
> anotherFunc( u.a, u.b, u.c, u.d );
>
> }
>
> Will this code work with DMD and GDC?  And does the D language
specification
> guarantee this code will always work, so I don't have to worry about every
other
> potential compiler implementations in the future?
>
> Thanks.
>
>

With the struct I think D can insert padding between the bytes to get appropriate alignment - though I don't remember exactly what the spec says about that. It might be better to cast to a byte* and use array indexing.

int main() {
 int x = 0x11223344;
 byte* y = cast(byte*)&x;
 printf("%x %x %x %x \n",y[0],y[1],y[2],y[3]);
 return 0;
}


December 01, 2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Ben Hinkle schrieb am Wed, 1 Dec 2004 13:55:19 -0500:
><newbie@d.com> wrote in message news:col0rk$1kj$1@digitaldaemon.com...
>> Without bit shifting, what's the correct way to split a int (32-bits) into 4 bytes?  BTW, I don't care about the byte order:
>>
>> union U {
>> int i;
>> struct { byte a, b, c, d; }
>> }
>>
>> U u;
>>
>> void splitInt32( int x ) {
>> u.i = x;
>>
>> // use the bytes ...
>> anotherFunc( u.a, u.b, u.c, u.d );
>>
>> }
>>
>> Will this code work with DMD and GDC?  And does the D language specification guarantee this code will always work, so I don't have to worry about every other potential compiler implementations in the future?

> With the struct I think D can insert padding between the bytes to get appropriate alignment - though I don't remember exactly what the spec says about that.

In theory, that's what the align keyword is for:
# union U {
#    int i;
#    align (1) struct{
#        byte a;
#        byte b;
#        byte c;
#        btye d;
#    }
# }

In praxis ... http://svn.kuehne.cn/dstress/www/dstress.html#align_06

indicates that the align keyword has no effect when used with gcc(for
linking under Linux).

Thomas


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.9.12 (GNU/Linux)

iD8DBQFBrhjY3w+/yD4P9tIRAq+4AKC9RQTtkbQepBLrgNe2iOIhDv8ppQCfXGjI
rVpVsYaY4Q6ecVvd5ilBnQU=
=PXIH
-----END PGP SIGNATURE-----
December 01, 2004
In article <ovh182-ev4.ln1@kuehne.cn>, Thomas Kuehne says...
>
>In praxis ... http://svn.kuehne.cn/dstress/www/dstress.html#align_06
>
>indicates that the align keyword has no effect when used with gcc(for
>linking under Linux).

Haa! why you only mention gdc?  actually that test fails for all the compiler versions:

--------------------------------------------------------------------
dmd 0.93	dmd 0.95	dmd 0.96	dmd 0.98	dmd 0.99	dmd 0.100	dmd 0.101	dmd 0.102	gdc
1g	dmd 0.104	gdc 0.8	gdc 0.8
Mac 	dmd 0.105	dmd 0.106	dmd 0.108
--------------------------------------------------------------------
align
06	fail	fail	fail	fail	fail	fail	fail	fail	fail	fail	fail	fail	fail	fail	fail
--------------------------------------------------------------------



December 01, 2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

newbie@d.com schrieb am Wed, 1 Dec 2004 20:27:11 +0000 (UTC):
> In article <ovh182-ev4.ln1@kuehne.cn>, Thomas Kuehne says...
>>
>>In praxis ... http://svn.kuehne.cn/dstress/www/dstress.html#align_06
>>
>>indicates that the align keyword has no effect when used with gcc(for
>>linking under Linux).
>
> Haa! why you only mention gdc?  actually that test fails for all the compiler versions:
<snip>

Please read again I wrote GCC, not GDC.

On Windows you usually compile with DMD and link the objects/libraries with DMC.

DMC doesn't support Linux, thus Linux users have to use other means. GCC is the common choice. GDC is not involved during DMD->GCC building on Linux, but is a compiler on it's own.

I haven't got a Windows box, thus can't test it myself. If you are interested in "align" under Windows, I'd suggest you download

http://svn.kuehne.cn/dstress/run/align_06.d

, compile, link, execute and report back.

Thomas


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.9.12 (GNU/Linux)

iD8DBQFBrjET3w+/yD4P9tIRAgSwAKDF68sOkLLpyhCx6llklLXTof8YVgCcCLpD
mQH+ZdvYyl2cSuYa65wLk7s=
=AwMO
-----END PGP SIGNATURE-----
December 01, 2004
In article <j1o182-7u5.ln1@kuehne.cn>, Thomas Kuehne says...
>
>Please read again I wrote GCC, not GDC.
>

Sorry.  But are you refering to the linker? then I'm confused: is this a compiler issue, or linking issue?

>I haven't got a Windows box, thus can't test it myself. If you are interested in "align" under Windows, I'd suggest you download
>
>http://svn.kuehne.cn/dstress/run/align_06.d
>
>, compile, link, execute and report back.
>

Tried, and failed:

D:\tmp>align_06.exe
Error: AssertError Failure align_06.d(17)


Now I think my question is: given the current compiler implementation,   what's
the fastest way (in theory) to split int into bytes?  bit-shifting, or array
indexing by casting to (byte*).

Haven't done the experient yet, like to hear your opinion (in theory) first.



December 01, 2004
>Now I think my question is: given the current compiler implementation,   what's
>the fastest way (in theory) to split int into bytes?  bit-shifting, or array
>indexing by casting to (byte*).

Hm. I use this:

align(1) union int2bytes
{
uint     theInt;
ubyte[4] theBytes;
static assert (int2bytes.sizeof == 4);
static assert (int2bytes.alignof == 1);
}
Is it good? :)


December 01, 2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

newbie@d.com schrieb am Wed, 1 Dec 2004 21:31:40 +0000 (UTC):
>>Please read again I wrote GCC, not GDC.
>>
>
> Sorry.  But are you refering to the linker? then I'm confused: is this a compiler issue, or linking issue?
>

Usually I would expect this to be a compiler issue, but it might as well
be a "communication" within the toolchain.
The Linux "linking" stage for D involves more than just plain linking via LD.

>>I haven't got a Windows box, thus can't test it myself. If you are interested in "align" under Windows, I'd suggest you download
>>
>>http://svn.kuehne.cn/dstress/run/align_06.d
>>
>>, compile, link, execute and report back.
>>
>
> Tried, and failed:
>
> D:\tmp>align_06.exe
> Error: AssertError Failure align_06.d(17)

Hurry up and send a bug report to the digitalmars.D.bugs newsgroup ;)

> Now I think my question is: given the current compiler implementation,   what's
> the fastest way (in theory) to split int into bytes?  bit-shifting, or array
> indexing by casting to (byte*).
>
> Haven't done the experient yet, like to hear your opinion (in theory) first.

Do you use constant values for indexing / bit-shifting?
( x[2] / x>>16 versus x[n] / x>>n )

Don't you intend to effectifly use byte-shifts instead of bit-shifts?
( x>>(8*n) insted of x>>m; n,m=[0,1,..])

Compile some samples and have a look at the assembler output.

Thomas


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.9.12 (GNU/Linux)

iD8DBQFBrkS/3w+/yD4P9tIRAm7iAKCIKYu3CEXFraqHRtJOwDNWGhLuPACgtY0Z
s2jPIjcEX2xjUl2F4H4P/xo=
=bn+g
-----END PGP SIGNATURE-----
December 02, 2004
newbie@d.com wrote:

> Without bit shifting, what's the correct way
> to split a int (32-bits) into 4 bytes?

Why *not* use regular bit shifting ?

>   uint     i;
>   ubyte[4] b;


Something like this: (ands are optional)

1)
>   b[0] = (i >>> 24);
>   b[1] = (i >>> 16) & 0xFF;
>   b[2] = (i >>>  8) & 0xFF;
>   b[3] =  i         & 0xFF;

It's probably a whole lot easier... ?
Not to mention faster, avoids storing.
(going to memory is bound to be slow)


But you could do that too, if you like:

2)
>   *(cast(uint*) b) = i;

Or with a union, to avoid the casting.
(beware of union/alignment bugs, though)


Or you could just use a byte pointer
instead of a new variable, then you
only need to cast the int pointer...
(either to a temp, or when using it)

>   ubyte*   b;

3)
>   b = cast(ubyte*) &i;

Then you can use b[0] just as with an array.
("static array", that is, such as ubyte[4])


Or depending on what you want it for, you
could use 4 variables instead of an array
to "help" the compiler avoid storing them
in memory but use the registers instead ?

>   ubyte b0,b1,b2,b3;

And then just use "b0" instead of "b[0]",
when bitshifting from the 32-bit integer.
But smart compilers should do that anyway.


At the end of the day, it depends on *why*
you want to split it and what to use it for?

--anders

PS. These three examples do work with GDC.