www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Bug in pointer arithmetics

reply Niko Korhonen <niktheblak hotmail.com> writes:
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.
Mar 07 2005
next sibling parent reply Derek Parnell <derek psych.ward> writes:
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
Mar 07 2005
parent Niko Korhonen <niktheblak hotmail.com> writes:
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.
Mar 07 2005
prev sibling next sibling parent reply zwang <nehzgnaw gmail.com> writes:
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.

Mar 07 2005
parent Thomas Kuehne <thomas-dloop kuehne.thisisspam.cn> writes:
-----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-----
Mar 17 2005
prev sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
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. 

Mar 07 2005