FB II Compiler







Disk I/O














Made with FB


Comprehend the # and @ symbols along with parameters

What is "#"?

In FB, parameters are understood by the language. If you CALL FRAMERECT(t), FB knows to pass a pointer to the variable "t" instead of pushing the value contained in "t".

Sometimes you may want to override this and you do it with the pound symbol.

DIM t,l,b,r
vPtr& = @t : REM get the address of the variable "t"

What is "@"?

Sometimes, you need to know the address of a variable. For this we use the at ("@") symbol. Here's a way it might be used.

LOCAL FN frameAndShrink(@rect&)
CALL INSETRECT(rect&.nil%,1,1)

DIM t,l,b,r
CALL SETRECT(t,10,10,50,50)

REM rect is now 40 x 40
FN frameAndShrink(t)
REM rect is now 38 x 38

STAZ ~)~

In some Toolbox calls in which FutureBasic must provide a memory address to the Toolbox, the "normal" FB syntax requires a parameter in the form of a variable name--FB then determines the variable's address and passes that address along to the Toolbox. For example:

CALL SETRECT(rect, 10,10, 200, 250)

In this call, FB passes the address of the "rect" variable along to the Toolbox, and the Toolbox then stores the rectangle data into rect.

But sometimes you may wish to have FB pass some _other_ address, that is not necessarily the address of any FB variable. That is what the "#" syntax is for. If you follow "#" with an expression that evaluates to an address, then FB will pass _that_ address to the ToolBox. For example:

CALL SETRECT(#rectAddr&, 10, 10, 200, 250)

In this case, SETRECT stores the rectangle data into the 8 bytes which begin at the address specified by rectAddr&.

Another way to put it is that "#" allows you to pass a parameter "by value" which would otherwise be passed "by reference."

More again...

Many Toolbox routines need to know the address where some data is stored (rather than simply knowing the contents of the data). The way this is typically implemented in FB is:
(1) You create an FB variable (possibly storing some data in it);
(2) you specify the variable as a parameter when you make the Toolbox call; and then
(3) FB internally passes the variable's _address_ to the Mac Toolbox.

But sometimes it's useful for you to pass an _arbitrary_ address to the Toolbox routine--an address which may or may not be occupied by an FB variable. That's where the "#" syntax comes in. When you pass a long-integer expression to the Toolbox routine, and precede the expression with "#", then FB evaluates the expression as an address, and passes _that_ address to the Mac Toolbox. Here's an example: Suppose we have an 8-byte variable called "rect" which happens to be located at address 27505392. Then suppose we do this:

CALL SETRECT(rect, 10,10, 250, 350)

It turns out that SetRect likes an address as its first parameter, so FB passes the number 27505392 (the address of rect) to the Toolbox.

But now suppose that you really want to pass some _other_ address to SetRect: say the address that's 14 bytes inside some handle h&, rather than the address of some FB variable. You can do it like this:

CALL SETRECT(#[h&]+14, 10, 10, 250, 350)

Because of the "#", FB knows that what follows should be interpreted as a long integer expression. It evaluates that expression (in this case, the expression indicates some address in the "heap"), and it passes that value to SetRect. SetRect will then dutifully alter 8 bytes inside that handle, rather than 8 bytes in some FB variable.

The "#" syntax doesn't work for all parameters in all Toolbox routines. It only works for parameters where _both_ of these apply:
(a) the MacOS expects an address, and
(b) FB (normally) expects a _variable_ (whose address FB extracts internally).

In such special cases, you're allowed to specify the Toolbox parameter in either of the following ways:

<var> (in this case, FB passes the address of <var> to the Toolbox)
#<expr&> (in this case, FB passes the value of <expr&> to the Toolbox)

In a few weird situations, it's convenient to keep your data in a variable (suggesting the first of the 2 syntaxes above), but the FB compiler just doesn't like the particular type of variable you're using. People get around this problem by using the second syntax, but substituting the variable's address for <expr&>, like so:


This has led some people to look at the "#" syntax as a kind of way to "override type-checking" of parameter variables; but I think this is a misleading way to look at it, because it can be used for other purposes, and it can be used without variables at all (for example, you can pass #_nil), and especially because the "#" won't even compile except in certain parameters in certain Toolbox routines.

Since FB is not 100% consistent in the way it interprets Toolbox parameters, sometimes it takes trial-and-error to figure out which parameters will accept "#". For example, in FB's implementation of GETCATINFO, condition "(a)" is satisfied, but not condition "(b)".
So "#" can't be used in GETCATINFO. But in other routines such as SETRECT or (as you've discovered) BITTST, both "(a)" and "(b)" are satisfied, so "#" works.