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. This makes Tibbo BASIC arrays and structures safe.


As in C, BASIC arrays count elements from 0 (not a useless note — some old BASIC implementations counted from 1). Here are some 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 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 binary data. In this case, the 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 and 16-bit members of C structures and unions.


Arrays, Structures, Unions

Arrays and Structures in Tibbo BASIC

Arrays, Structures, and Unions in Tibbo C

Padding