IonicWind Software

Aurora Compiler => General Discussion => Topic started by: Mike Stefanik on February 06, 2006, 01:55:50 AM

Title: Possible bug with pointer arrays
Post by: Mike Stefanik on February 06, 2006, 01:55:50 AM
If you have an array of pointers to strings, you can do something like this:


    pointer lpValues[MAXVALUES];
    pointer lpValue;
    int nIndex;

    // Assume the lpValues array has been initialized at this point
    // with each element pointing to a null-terminated string

    for (nIndex = 0; nIndex < MAXVALUES; nIndex++)
    {
         lpValue = lpValues[nIndex];
        pListBox->AddString(*(string)lpValue);
    }


That code works fine. However, curiously enough, the following code won't work:


    pointer lpValues[MAXVALUES];
    int nIndex;

    // Assume the lpValues array has been initialized at this point
    // with each element pointing to a null-terminated string

    for (nIndex = 0; nIndex < MAXVALUES; nIndex++)
    {
        pListBox->AddString(*(string)lpValues[nIndex]);
    }


My guess would be that there's some kind of operator precendence problem when casting an element of an array vs. a plain variable. Trying to do this results in a parsing error:


pListBox->AddString(*(string)(lpValues[nIndex]));


That would also appear to be a bug in the parser.
Title: Re: Possible bug with pointer arrays
Post by: lviklund on February 06, 2006, 05:09:18 AM
I have also struggled with this.
I presumed it was a bug in my head  :).

Looking forward to an explanation to where the bug is located.

/Lasse
Title: Re: Possible bug with pointer arrays
Post by: Rock Ridge Farm (Larry) on February 06, 2006, 07:14:18 AM
Unless I am mistaken (happens a lot).
You allocated an array of pointers but no actual storage for the strings.
The pointer will just be an address. You still need actual storage for the stirng.
Title: Re: Possible bug with pointer arrays
Post by: Parker on February 06, 2006, 08:13:40 AM
I think the parser isn't seeing [] before *. But something like this works
*(string)(variable + 4*nIndex)
4 is the size of a 32 bit pointer.
Title: Re: Possible bug with pointer arrays
Post by: Mike Stefanik on February 06, 2006, 08:15:51 AM
In that little code snippet, presume that the pointers in the array are valid and the string space is allocated. The problem appears to be how the compliler is generating code when you attempt to cast a value for an element of an array instead of a regular variable. In other words, to boil it down, the following code works:


p = a[n];
function(*(string)p);


The following code should be equivalient to the above, but the compiler (apparently) doesn't handle it correctly:


function(*(string)a[n]);


The above code only works if 'n' is the first element (0) of the array. If n > 0, then it breaks.

Edit: Yup, you can do pointer arithmetic to get around the problem, but its an ugly hack (and generally speaking, assuming that an integer value is always 4 bytes wide is non-portable).
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 06, 2006, 08:20:42 AM
Use pointer math.   Typecasting has higher precedence than the array operator currently and reversing that will break other things.

It was something I was going to look at in the future when I had a few hours to kill.  Pointer math will always work no matter what changes in precedence though.

Paul.

Title: Re: Possible bug with pointer arrays
Post by: Parker on February 06, 2006, 08:26:00 AM
Quote from: Mike Stefanik on February 06, 2006, 08:15:51 AMand generally speaking, assuming that an integer value is always 4 bytes wide is non-portable

That's why we need the sizeof() function to work, so instead you can do
*(string)(variable + sizeof(pointer)*nIndex);
which would work on 64 bit systems when aurora supports them too.

My idea is to have len stay how it is now, where it can still be used to determine UDT lengths, but sizeof() be added that can't do string length but just tells what the size of a built in variable type, or a UDT length.
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 06, 2006, 08:32:03 AM
LEN can be changed for intrinsic types too.  This isn't C so I had no plans on adding 'sizeof' since we already have two length operators.
Title: Re: Possible bug with pointer arrays
Post by: Mike Stefanik on February 06, 2006, 08:45:25 AM
Just so you know "sizeof" does show up as a keyword in the editor. It made me think that had been implemented, until I tried to actually use it. Personally I think that the use of a function like len() instead of a sizeof operator is a bit confusing, but Visual Basic does the same thing so I guess folks are used to that these days.

Back to the array issue, I've found that the pointer arithmetic doesn't work as expected either. Let's say that you have the following block of text in memory (\0 will represent a null byte): "abcdefghijk\0lmnopqrs\0tuvwxyz\0" and you setup an array of pointers where a[0] points to the first null-terminated string (ie: "abcdefghijk"), a[1] points to the second string and so on.

If you use the two-step approach, then everything works correctly:


for (n = 0; n < 3; n++)
{
    p = a[n];
   writeln(*(string)p);
}


All well and good. However, if you use pointer math things go screwy:


for (n = 0; n < 3; n++)
{
    writeln(*(string)(a + (n * 4)));
}


In the second case, instead of getting "abcdefghijk", "lmnopqrs" and "tuvwxyz" as output, you'll get "abcdefghijk", "efghijk" and "ijk". Instead of advancing through the array, it's advancing through what the first element of the array points to. It seems to be treating "a" as the same as "&a[0]" which would be wrong.
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 06, 2006, 08:53:49 AM
Pointer math works for an array of the some sized elements, the string type is 255 bytes long so you wouldn't be accessing the correct location  You need two type casting operators maybe.

*(string)*(pointer)(p + n*4);

Haven't looked into it yet.  But I can understand why it is happening.

Again the array operators will be fixed when I have a few hours to kill.  Right now the IDE is being ripped apart on my end so I can't test your code yet ;)
Title: Re: Possible bug with pointer arrays
Post by: Mike Stefanik on February 06, 2006, 08:56:22 AM
No worries, just something to point out for future reference. The work-around is simple and in some cases can actually make the code a bit clearer to read. :)
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 06, 2006, 08:58:03 AM
sizeof can be an alias for LEN.  Just didn't see the point in having three separate 'length' functions.

It's colored blue because I used the C keyword table of Scintilla as a starting point.  Just haven't gone through and removed all of the non-existing ones yet.

Paul.
Title: Re: Possible bug with pointer arrays
Post by: Parker on February 06, 2006, 01:33:45 PM
What's the second already existing one? I only know of LEN.
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 06, 2006, 02:02:25 PM
len and baselen
Title: Re: Possible bug with pointer arrays
Post by: lviklund on February 08, 2006, 09:02:16 AM
I don't get it ???.

Why does this work:
Quotemessagebox(null, str$((*(SBall)pBalls.posX)), "");

but not this:
Quotemessagebox(null, str$((*(SBall)pBalls.posX) + (RADIUS/2)), "");

As Larry said. Take it slowly. I need to understand this.

Lasse
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 08, 2006, 09:06:57 AM
What doesn't work?  a compiler error, a crash, unexpected result?  Be a bit more specific ;)
Title: Re: Possible bug with pointer arrays
Post by: lviklund on February 08, 2006, 10:12:20 AM
Oh, I thought you could read my mind.
Actually my previous post works but that just makes it even more confusing.
I have to include the stripped code again.

Here it is:
SillyBalls with pointers ;D ;D ;D.

This works but if you take away the /* around the IF clauses in DrawBalls strange things starts to happen.

File: E:\EGEN_Kod\Aurora\Demos\SillyBalls_with_pointers\DemoBalls_with_pointers.src (117) unsupported use of * - {

#autodefine "off"

#typedef uint unsigned int

#define WINDOW_WIDTH  400
#define WINDOW_HEIGHT 400

#define RADIUS        10
#define NUM_BALLS      3
#define MAX_VELOCITY  3

declare import, GetTickCount(),uint;

struct SBall
{
  int posX;  //to hold the balls coordinates
  int posY;
  int velX;  //and velocity
  int velY;
  int ball_color; //Some fancy colors
}

class mywindow : window
{
//overridden functions.
declare OnClose(),int;
declare OnCreate(),int;
declare OnPaint(),int;
declare DrawBalls(),int;
declare SetUpBalls(),int;

RECT rect;
int cxClient, cyClient, cwClient, chClient;
SBall balls[NUM_BALLS];
pointer pBalls[NUM_BALLS];
}

global sub main()
{
mywindow w;
w.Create(0,0,WINDOW_WIDTH,WINDOW_HEIGHT,AWS_CAPTION|AWS_VISIBLE|AWS_SYSMENU,0,"Silly balls!!",0);

do
{
wait();
}until w.m_hwnd = 0;
return;
}

mywindow::OnClose(),int
{
Destroy();
return TRUE;
}

mywindow::OnCreate(),int
{
CenterWindow();
SetUpBalls();
return true;
}

mywindow::OnPaint(),int
{
DrawBalls();
return true;
}

mywindow::SetUpBalls(),int
{
rect = GetClientRect();
cxClient = rect.left;
cyClient = rect.top;

cwClient = rect.right-rect.left;
chClient = rect.bottom-rect.top;

//seed random number generator
seedrnd(GetTickCount());

//set up the balls with random positions and velocities
for (int i=0; i<NUM_BALLS; i++)
{
pBalls[i] = new(SBall,len(SBall));

*(SBall)pBalls[i].posX = Rand((RADIUS/2), cwClient - (RADIUS/2));
*(SBall)pBalls[i].posY = Rand((RADIUS/2), chClient - (RADIUS/2));
*(SBall)pBalls[i].velX = Rand(1,MAX_VELOCITY);
*(SBall)pBalls[i].velY = Rand(1,MAX_VELOCITY);
*(SBall)pBalls[i].ball_color = RGB(rand(255),rand(255),rand(255));
}

//DrawBalls();
return true;
}

mywindow::DrawBalls(),int
{
uint cacheDC;
cacheDC = GetHDC();
DrawMode(TRANSPARENT);

for (int i=0; i<NUM_BALLS; i++)
{
//check to see if they have hit any walls and reverse velocity
//accordingly

//messagebox(null,str$(*(SBall)pBalls[i].posX + (RADIUS/2)),"");
//messagebox(null,str$(*(SBall)pBalls[i].posX),"");

/* if (*(SBall)pBalls[i].posX + (RADIUS/2) >= cwClient or *(SBALL)pBalls[i].posX - (RADIUS/2) < 0)
{
*(SBall)pBalls[i].velX = -(*(SBall)pBalls[i].velX);
}

if (*(SBALL)pBalls[i].posY + (RADIUS/2) >= chClient or *(SBALL)balls[i].posY - (RADIUS/2) < 0)
{
*(SBall)pBalls[i].velY = *(SBall)pBalls[i].velY;
}
*/ // update their position
*(SBall)pBalls[i].posX += *(SBall)pBalls[i].velX;
*(SBall)pBalls[i].posY += *(SBall)pBalls[i].velY;

//render to display
Circle(*(SBall)pBalls[i].posX, *(SBall)pBalls[i].posY, RADIUS,
*(SBall)pBalls[i].ball_color, *(SBall)pBalls[i].ball_color);

}
DrawMode(OPAQUE);
WriteText(rect.left+20,rect.bottom-20, "Last ball number: " + str$(i) + " ready. " +
str$(*(SBall)pBalls[i].velX) + " " +
str$(*(SBall)pBalls[i].velY) + " " + str$(RADIUS));

ReleaseHDC(cacheDC);
return true;
}



It seems like IF's don't like me.

Lasse
Title: Re: Possible bug with pointer arrays
Post by: Ionic Wind Support Team on February 08, 2006, 02:18:38 PM
As mentioned before array operators have lower precendence than type casting.  It's something we are working on.
Title: Re: Possible bug with pointer arrays
Post by: lviklund on February 08, 2006, 02:38:06 PM
Yes
That's why I get so confused when this worked:

messagebox(null,str$(*(SBall)pBalls[i].posX + (RADIUS/2)),"");

(Above the if's in my previous post)

Anyway, I put this on ice for now.