Microsoft KB Archive/65287

= Must Use BYVAL at Both Ends When CALLing 7.10 SUB or FUNCTION =

Article ID: 65287

Article Last Modified on 8/16/2005

-

APPLIES TO


 * Microsoft BASIC Professional Development System 7.1

-



This article was previously published under Q65287



SUMMARY
When passing parameters by value to a Basic SUBprogram or FUNCTION procedure, you must use the BYVAL attribute from both the calling end and the receiving end.

By itself, using BYVAL in the SUB or FUNCTION statement (at the receiving end) isn't enough to tell the SUB or FUNCTION to pass by value. If you don't also use the BYVAL attribute in the CALL statement or the DECLARE statement, then by default Basic will pass by reference and push only the address of the variable on the stack. If you mistakenly use BYVAL only at the calling end or only at the receiving end, then an incorrect value will be passed.

This information only applies to Microsoft Basic Professional Development System (PDS) version 7.10, since passing parameters to Basic SUBprograms and FUNCTIONS with the BYVAL attribute was first introduced version 7.10.



MORE INFORMATION
Note for Versions Earlier Than 7.10: In Microsoft Basic PDS version 7.00, in Microsoft Basic Compiler versions 6.00 and 6.00b, and in QuickBasic versions 4.00, 4.00b, and 4.50, you could not DECLARE or CALL a Basic routine with parameters having the BYVAL attribute, since BYVAL could be used only for parameters of non-Basic routines (such as C or Macro Assembler).

NOTE: If you create a program in an editor outside the QBX.EXE environment without DECLARE statements at the top of the program, DECLARE statements will not automatically be added to your code. As a result, a SUB statement that contains a formal parameter with the BYVAL attribute (at the receiving end) will have no BYVAL declaration at the calling end. Instead of specifying BYVAL in a DECLARE statement, you can specify BYVAL in the CALL statement.

Code Example: Incorrect Way to Pass by Value
The program below, written in an editor outside of the QBX.EXE environment, will pass the offset of the variable A& to the SUBprogram, although the SUBprogram is expecting the actual value contained in A&. This happens because each end of the call to the SUBprogram acts blindly on the information that it has. The call to TestPass blindly assumes that it is passing a value by reference, which is the default. It therefore passes the offset (in this case 3030) of the variable A& to the SUBprogram TestPass. The SUBprogram TestPass is expecting to receive the value of the variable A&, as is dictated by the BYVAL attribute in the SUB statement. The program therefore prints 3030 (the offset) on the screen, instead of the constant 2 (the value). CALL TestPass (2&) 'Notice no declaration of BYVAL in CALL or                    'DECLARE, so default is pass (send) by reference. SUB TestPass(BYVAL A&) 'BYVAL in SUB says to pass (receive) by value. B& = A&   PRINT A&        ' Prints 3030, the offset of A&. END SUB

Correct Way to Pass by Value, Using BYVAL in DECLARE and SUB
DECLARE SUB TestPass(BYVAL A&) ' BYVAL in the above DECLARE means to pass (send) by value. CALL TestPass (2&) SUB TestPass(BYVAL A&) 'BYVAL in SUB means pass (receive) by value. B& = A&   PRINT A&      ' prints 2, the value (contents) of A& END SUB

Another Correct Way to Pass by Value, Using BYVAL in CALL and SUB
CALL TestPass (BYVAL 2&) 'BYVAL in CALL means pass (send) by value. SUB TestPass(BYVAL A&)   'BYVAL in SUB means pass (receive) by value. B& = A&   PRINT A&      ' prints 2, the value (contents) of A& END SUB