Arrays, Structures, Unions
Tibbo BASIC and Tibbo C support arrays and structures but the storage format in RAM differs between the two languages.
There is no compatibility: you cannot pass an array or a structure from a BASIC procedure to a C function, or vice versa.
There is no inherent limitation to the maximum number of array dimensions or the number of levels in a structure.
Unions are only supported in Tibbo C.
Arrays and structures in Tibbo BASIC
Like strings, arrays and structures in Tibbo BASIC contain 2-byte headers ensuring their safe handling.
Structures have multiple headers — one for each leaf of the structure's "tree".
Headers contain pointers to array and structure descriptors, which are compiled into the .TPC binary.
Owing to these headers, the VM is able to catch out-of-range access situations, thus preventing memory corruption (see ABORT(OOR) exception in Debugging).
This makes Tibbo BASIC arrays and structures safe.
As in C, BASIC arrays count elements from 0 (not a useless note — some old BASIC implementation counted from 1).
Examples of array and structure definitions and use:
** Tibbo Basic **
sub on_sys_init
dim x(5) as byte 'a byte array with 5 members
dim s_array(5,2) as string(10) 'a two-dimensional array (5 "rows" of 2 "columns") of strings having a limited capacity of 10 bytes each
type foo_struct 'structure with two members, and both are arrays
x(10) as byte
s(10) as string(4)
end type
type bar_struct 'structure with two members, one if which is another structure
foo as foo_struct
w as word
end type
dim bar(3) as bar_struct 'an array of type "bar_struct"
'then somewhere inside a function or a sub:
dim f as byte
for f=0 to f=4 'x has five members (0~4), and this is the "rightmost" one
x(f)=f
next f
s_array(2,1)="Element 2,1"
bar(1).foo.s(2)="test" 'woo-hoo! Addressing the element 2 of the member s of the member foo of element 1 of bar!
end sub
Arrays, structures, and unions in Tibbo C
Arrays, structures, and unions of Tibbo C contain no special headers. They are implemented in the standard ANSI C way.
Therefore, they are not safe and your runaway program can easily cause out-of-range and memory corruption situations.
In C, there is a close relationship between arrays and pointers. These two entities are often interchangeable. Having extra headers would break this straightforward relationship.
It is also a common practice in C to process data by putting a structure over it. For example, if you're processing network packets, the data format is defined by a structure. In C, you would create a pointer of this structure's type, then point the pointer (with a cast) to a byte array. You can then work with the packet data "through" the structure.
If we had extra headers like in BASIC, then the straightforward conversion between a block and binary data and structures would be impossible. It's for this reason that we implemented C arrays, structures, and unions in a 100 percent standard way; this preserves all the abilities of the C language. Regrettably, this also brings with it all the "unsafeness" of C.
The following C code example is impossible to implement in Tibbo BASIC. It parses two types of data packets — "PACKET_X" and "PACKET_Y".
This is a classic example of using unions and structures to look at the binary data.
In this case, this binary data is supposed to be prepared in the incoming_data[] array.
** Tibbo C **
#define PACKET_X 0x00
#define PACKET_Y 0x01
struct packet_x{
unsigned char packet_type;
unsigned int source_id;
unsigned int dest_id;
unsigned char payload_len;
};
struct packet_y{
unsigned char packet_type;
unsigned int source_id;
unsigned char payload_len;
};
union packet{
packet_x p_x;
packet_y p_y;
};
unsigned char incoming_data[]; //this code example doesn't show how binary data gets into the array
...
void process_data(){
unsigned int source_id,dest_id=0xFF;
unsigned char payload_len;
packet *packet_ptr=(packet *)&incoming_data;
if(packet_ptr->p_x.packet_type==PACKET_X){
source_id=packet_ptr->p_x.source_id;
dest_id=packet_ptr->p_x.dest_id;
payload_len=packet_ptr->p_x.payload_len;
}
else{
source_id=packet_ptr->p_y.source_id;
dest_id=0xFF;
payload_len=packet_ptr->p_y.payload_len;
}
}
Padding
Tibbo C compiles with the default #pragma pack value of (1). This means no padding for 8-bit and 16-bit members of C structures and unions.