www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - correct way to split int into bytes?

reply newbie d.com writes:
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.
Dec 01 2004
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
<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

 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

 guarantee this code will always work, so I don't have to worry about every

 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; }
Dec 01 2004
parent reply Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----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-----
Dec 01 2004
parent reply newbie d.com writes:
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 --------------------------------------------------------------------
Dec 01 2004
parent reply Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----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:

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-----
Dec 01 2004
parent reply newbie d.com writes:
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.
Dec 01 2004
next sibling parent Dr.Dizel <Dr.Dizel_member pathlink.com> writes:
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? :)
Dec 01 2004
prev sibling parent Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----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-----
Dec 01 2004
prev sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
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.
Dec 02 2004