Structs and layout
A type lays its fields out the way C lays out a struct on the same
platform. So a type with the same fields in the same order as a C struct has
the same size and offsets, and C can fill one in, read one, or return one.
'' A type has C's struct layout, so C can fill one in or return one.
type DivResult
as int32 quot
as int32 rem_ '' a field cannot be named rem: rem is a comment
end type
extern "C"
declare function div( byval num as int32, byval den as int32 ) _
as DivResult
end extern
var r = div( 47, 10 )
print "div( 47, 10 ): quot"; r.quot; ", rem"; r.rem_
'' Natural alignment: value starts on a 4-byte boundary, as in C.
type Natural
as uint8 tag
as int32 value
end type
'' field = 1 packs the fields, as C's #pragma pack( 1 ) does.
type Packed field = 1
as uint8 tag
as int32 value
end type
print "Natural: size"; sizeof( Natural ); _
", value at"; offsetof( Natural, value )
print "Packed: size"; sizeof( Packed ); _
", value at"; offsetof( Packed, value )
'' A fixed-size zstring is an inline char array, like C's char[ 8 ].
type Record
as zstring * 8 label
as int32 id
end type
print "Record: size"; sizeof( Record ); _
", id at"; offsetof( Record, id )
Output
div( 47, 10 ): quot 4, rem 7
Natural: size 8, value at 4
Packed: size 5, value at 1
Record: size 12, id at 8
C's div returns a div_t, a struct of two ints, by value. DivResult has
the same two fields, so the declaration can say it returns a DivResult, and
tiko passes it back by the platform's rules exactly as a C compiler would. The
field names do not have to match C's, only the types and the order; rem is
the one name that cannot be used, because rem starts a comment.
Alignment. Each field sits on a boundary of its own size, with padding
before it where needed, and the whole type is rounded up to its largest
alignment. That is why Natural is 8 bytes and not 5. offsetof( T, field )
gives a field's offset, to check against the C header.
Packing. field = 1 removes the padding, as C's #pragma pack( 1 ) does;
field = 2 and field = 4 limit the alignment the same way. Use them only to
match a C struct that is packed. An unpacked C struct read through a packed
type is garbage.
A fixed-size zstring * n is an inline array of n characters, like C's
char name[ n ]. A ustring field is not: it holds a pointer to its text, and
never belongs in a struct that C will read.
Activities
- Add an
int64field aftervalueinNaturaland predict the new size. - Declare C's
lldiv, which returns twolong longs, and call it.