Thread overview
Bug in pointer arithmetics
Mar 07, 2005
Niko Korhonen
Mar 07, 2005
Derek Parnell
Mar 07, 2005
Niko Korhonen
Mar 07, 2005
zwang
Mar 17, 2005
Thomas Kuehne
Mar 07, 2005
Ben Hinkle
March 07, 2005
Consider the following code, meant to change the endian-ness of the argument:

uint flip(uint x)
{
  // The initial value shouldn't matter
  uint inverted = 555;

  ubyte* target = cast(ubyte*)&inverted;
  ubyte* source = cast(ubyte*)&x;

  // printf("source: %x\ntarget: %x\n",
  // cast(uint)source, cast(uint)target);
  target[0] = source[3];
  target[1] = source[2];
  target[2] = source[1];
  target[3] = source[0];

  return inverted;
}

void main()
{
  uint num = 1;
  printf("Original: %u flipped %u\n", num, flip(num));
}

This code always prints 555 for 'flipped' with DMD 0.115. But when you uncomment the printf line, it works as it should. When compiling with -O, it seems to set every byte of 'inverted' to 0x01.

It would appear that the compiler thinks that nothing is done with the argument 'inverted' during the function and returns it's initial value.
March 07, 2005
On Mon, 07 Mar 2005 14:51:22 +0200, Niko Korhonen wrote:

> Consider the following code, meant to change the endian-ness of the argument:
> 
> uint flip(uint x)
> {
>    // The initial value shouldn't matter
>    uint inverted = 555;
> 
>    ubyte* target = cast(ubyte*)&inverted;
>    ubyte* source = cast(ubyte*)&x;
> 
>    // printf("source: %x\ntarget: %x\n",
>    // cast(uint)source, cast(uint)target);
>    target[0] = source[3];
>    target[1] = source[2];
>    target[2] = source[1];
>    target[3] = source[0];
> 
>    return inverted;
> }
> 
> void main()
> {
>    uint num = 1;
>    printf("Original: %u flipped %u\n", num, flip(num));
> }
> 
> This code always prints 555 for 'flipped' with DMD 0.115. But when you uncomment the printf line, it works as it should. When compiling with -O, it seems to set every byte of 'inverted' to 0x01.
> 
> It would appear that the compiler thinks that nothing is done with the argument 'inverted' during the function and returns it's initial value.

If I might suggest an alternate method, without using pointers, and a bit more generic ...

<code>
import std.stdio;

template ByteFlip(T) {
T flip(T x)
{
   union F
   { T num;
     ubyte[num.sizeof] b;
   }
   F o;
   F i;
   o.num = 255; // The initial value shouldn't matter
   i.num = x;
   foreach(int i,ubyte c; i.b)
    o.b[length-i-1] = c;


   return o.num;
}
}
alias ByteFlip!(ubyte).flip flip;
alias ByteFlip!(ushort).flip flip;
alias ByteFlip!(uint).flip flip;
alias ByteFlip!(ulong).flip flip;

void main()
{
   ubyte num_byte = 1;
   ushort num_short = 1;
   uint num_int = 1;
   ulong num_long = 1;

   writefln("Original: %d byte flipped %d", num_byte, flip(num_byte));
   writefln("Original: %d short flipped %d", num_short, flip(num_short));
   writefln("Original: %d int flipped %d", num_int, flip(num_int));
   writefln("Original: %d long flipped %d", num_long, flip(num_long));

}
</code>

Seems to work regardless of -O switch.

-- 
Derek Parnell
Melbourne, Australia
8/03/2005 12:11:00 AM
March 07, 2005
Derek Parnell wrote:
> If I might suggest an alternate method, without using pointers, and a bit
> more generic ...

I wasn't trying to create the most elegant or the most effective byte flipping function possible, I was just coding for fun :)

I can certainly work around this issue easily, but I still think there's something wrong in the compiler and it should be addressed.

Also it seems that compiling my original example with -inline fixes the problem.
March 07, 2005
This seems to be a bug of casting...
Consider the following code:

<code>
uint f(){
	uint r;
	uint* p = cast(uint*)&r;
	*p = 1;
	return r;
}

uint g(){
	uint r;
	int* p = cast(int*)&r;
	*p = 1;
	return r;
}

void main(){
	assert(f()==1);  //OK
	assert(g()==1);  //<-- Assertion Error
}

</code>



Niko Korhonen wrote:
> Consider the following code, meant to change the endian-ness of the argument:
> 
> uint flip(uint x)
> {
>   // The initial value shouldn't matter
>   uint inverted = 555;
> 
>   ubyte* target = cast(ubyte*)&inverted;
>   ubyte* source = cast(ubyte*)&x;
> 
>   // printf("source: %x\ntarget: %x\n",
>   // cast(uint)source, cast(uint)target);
>   target[0] = source[3];
>   target[1] = source[2];
>   target[2] = source[1];
>   target[3] = source[0];
> 
>   return inverted;
> }
> 
> void main()
> {
>   uint num = 1;
>   printf("Original: %u flipped %u\n", num, flip(num));
> }
> 
> This code always prints 555 for 'flipped' with DMD 0.115. But when you uncomment the printf line, it works as it should. When compiling with -O, it seems to set every byte of 'inverted' to 0x01.
> 
> It would appear that the compiler thinks that nothing is done with the argument 'inverted' during the function and returns it's initial value.
March 07, 2005
Interestingly enough it looks like it works with
   ubyte[] target = (cast(ubyte*)&inverted)[0..4];
   ubyte[] source = (cast(ubyte*)&x)[0..4];

"Niko Korhonen" <niktheblak@hotmail.com> wrote in message news:d0hio7$2bs6$1@digitaldaemon.com...
> Consider the following code, meant to change the endian-ness of the argument:
>
> uint flip(uint x)
> {
>   // The initial value shouldn't matter
>   uint inverted = 555;
>
>   ubyte* target = cast(ubyte*)&inverted;
>   ubyte* source = cast(ubyte*)&x;
>
>   // printf("source: %x\ntarget: %x\n",
>   // cast(uint)source, cast(uint)target);
>   target[0] = source[3];
>   target[1] = source[2];
>   target[2] = source[1];
>   target[3] = source[0];
>
>   return inverted;
> }
>
> void main()
> {
>   uint num = 1;
>   printf("Original: %u flipped %u\n", num, flip(num));
> }
>
> This code always prints 555 for 'flipped' with DMD 0.115. But when you uncomment the printf line, it works as it should. When compiling with -O, it seems to set every byte of 'inverted' to 0x01.
>
> It would appear that the compiler thinks that nothing is done with the argument 'inverted' during the function and returns it's initial value.


March 17, 2005
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

zwang schrieb am Mon, 07 Mar 2005 21:42:55 +0800:
> This seems to be a bug of casting...
> Consider the following code:
>
><code>
> uint f(){
> 	uint r;
> 	uint* p = cast(uint*)&r;
> 	*p = 1;
> 	return r;
> }
>
> uint g(){
> 	uint r;
> 	int* p = cast(int*)&r;
> 	*p = 1;
> 	return r;
> }
>
> void main(){
> 	assert(f()==1);  //OK
> 	assert(g()==1);  //<-- Assertion Error
> }
>
></code>

Added to DStress as
http://dstress.kuehne.cn/run/cast_22.d

Thomas


-----BEGIN PGP SIGNATURE-----

iD8DBQFCOaDK3w+/yD4P9tIRAm6oAKCZn2vVa5hb4QX1Zy/CGjWVq+y0WwCeMdzY
oO/NnkeSHykwYj1kkCpb6J8=
=yNPw
-----END PGP SIGNATURE-----