Arrays, Structures, Unions

Top  Previous  Next

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.

Do you want to know why we implemented C arrays, structures, and unions differently?

In C there is a close relationship between arrays and pointers. These two entities are very often interchangeable. Having extra headers would break this straightforward relationship.

Also, it is a common practice in C to process data by putting a structure over it. Say, you are processing network packets. The data format is defined by a structure. What do you normally do in C? You 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. Well, if we had extra headers like in BASIC then the straightforward conversion between a block of binary data and structures would be impossible!

For this reason we implemented C arrays, structures, and unions in a 100% standard way. This preserves all the abilities of the C language. Regrettably, this also brings in 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 classical 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.