The B Programming Language 

 

Handling of Subprograms and Storage Management  

Function Definitions
Function definitions have the following form:

name (arguments ) statement 

The name is initialized to the rvalue of the function. The arguments consist of a list of names separated by commas. Each name defines an automatic lvalue that is assigned the rvalue of the corresponding function call's actual parameters. The statement (often compound) defines the execution of the function when invoked.

Recursion

putnumb(n) {

auto a;

if(a=n/10)       /*assignment, not equality test*/

putnumb(a);  */recursive*/ 

putchar(n%10 + '0');

}

This simplified version of the library function putnumb illustrates the use of recursion. (It only works for n>0.) "a" is set to the quotient of n/10; if this is non-zero, a recursive call on putnumb is made to print the quotient. Eventually, the high-order digit of n will be printed, and then, as each invocation of putnumb is popped, the next digit will be added on.

Argument Passing
Argument passing is call-by-value, which means that the called function is given the actual values of its arguments, and does not know their addresses. This makes it very difficult to change the value of one of the input arguments.

For instance, consider a function flip(x,y), which is intended to interchange its arguments. One might naively write

flip(x,y){

auto t;

t  = x;

x = y;

y = t;

}

but this has no effect at all. What one must do to accomplish the interchange is to pass the arguments as explicit addresses, and use them as addresses. Thus, the interchange can be invoked as

flip (&a,&b);

and the definition of the flip function is changed to

flip(x,y){

auto t;

t   = *y;

*x = y;

*y = t; 

The spaces on the right side of the equal signs must not be omitted. This problem does not arise if the arguments are vectors, since a vector is represented by its address.

Other Features

Calling FORTRAN and GMAP Subroutines from B Programs
B does not have floating point, multi-dimensional arrays, and similar data types that FORTRAN does better. A B program, callf, allows B programs to call FORTRAN and GMAP subroutines, such as:

callf(name, a1,a2,...,a10) ;

Here name is the FORTRAN function or subfunction to be used, and the a's are the zero or more arguments of the subroutine.

There are some restrictions on callf, related to the "call-by-value" problem.

  1. Variables that are not vectors must be referenced by address (for example, use "&x" instead of "x" as an argument).  
  2. No constants are allowed among the arguments, because the construction "& constant" is illegal in B. One cannot write

tod = callf(itimez,&0)

to get the time of day; instead one must use

t=0;

tod = callf(itimez,&t);

  1. It is not possible to return floating-point function values from FORTRAN programs, since the results are in the wrong register. They must be explicitly passed back as arguments. Thus one cannot write

s = callf(sin,&x)

but rather must write

callf(sin2,&x,&s)

where sin2 is defined as

subroutine sine2(x,y)

y = sin(x)

return

end

  1. callf is not blindingly efficient, since there is a lot of overhead in converting calling sequences.