Dunfield Development Services Inc.
Customer Support -- Application Note #0004
MICRO-C
Simulating structs/unions in older MICRO-C versions

Applies to: [Micro-C Compiler
]
Last updated: Sunday May 04, 2003
.
Application Note Index
[ Back ] [ Next ]

PROCEDURE
The 'C' constructs of structures and unions are not supported by versions of the MICRO-C compiler prior to 3.0. If you have version 2.xx or earlier
of MICRO-C, this application note describes ways by which you can achieve similar functionality to these constructs. If you have version 3.0 or
later, you do not need to use this application note, since you can define and use structures/unions directly.
If you are writing a new program, it is fairly easy to avoid these features, since equivalent functionality
can usually be accomplished with multiple arrays. Consider the structure definitions:
struct data_record {
char name[11]; /* A name (10+\0 chars max) */
char flags; /* Character type indicator */
unsigned value; /* A 16 bit value */
};
struct data_record records[10]; /* Declare actual variable space */
main()
{
strcpy(records[0].name, "test"); /* Write 1st name */
records[0].flags = 'A'; /* Write 1st type */
records[0].value = 0; /* Write 1st value */
print_record(&records[0]); /* Pass structure to function */
}
print_record(rec)
struct data_record *rec;
{
printf("%s:%c=%u\n", rec->name, rec->flags, rec->value);
}
You can write the above without structures as:
char record_name[10][11]; /* 10 names */
char record_flags[10]; /* 10 types */
unsigned record_value[10]; /* 10 values */
main()
{
strcpy(record_name[0], "test"); /* Write 1st name */
record_flags[0] = 'A'; /* Write 1st type */
record_value[0] = 0; /* Write 1st value */
printf_record(0); /* Pass index to function */
}
printf_record(r)
unsigned r;
{
printf("%s:%c=%u\n", record_name[r], record_flags[r],
record_value[r]);
}
There are occasions however when real structures would be useful, in the above example,
'printf_record'
can access only the one array of "pseudo structure's", whereas the version using structures could be passed a pointer to any structure
member anywhere. Another case where structures are required is when you want to group data in a certain layout, and treat it as a single block of memory.
We can obtain the entire functionality of structures by using the MICRO-C extended preprocessor
(MCP), and some parameterized macros. The technique
is to place your structure in an array (or use a pointer to the memory containing the structure), and define macros for each member, which add the
offset to that member, and use typecasting and indirection (if necessary) to access the required type at that address:
#define Rname(s) ((char*)(s+0)) /* Name */
#define Rflags(s) (*(char*)(s+11)) /* Type at offset 11 */
#define Rvalue(s) (*(unsigned*)(s+12)) /* Value at offset 12 */
#define Rsize 14 /* Total size */
char records[10][Rsize]; /* Array to hold structures */
main()
{
strcpy(Rname(records[0]), "test"); /* Write 1st name */
Rflags(records[0]) = 'A'; /* Write 1st type */
Rvalue(records[0]) = 0; /* Write 1st value */
print_record(records[0]); /* Pass member to function */
}
print_record(rec)
char *rec;
{
printf("%s:%c=%u\n", Rname(rec), Rflags(rec),
Rvalue(rec));
}
Notes:
The 'Rname' macro does not use indirection, since the name is a character array, and is expected to evaluate to an address. The
'Rflags' and 'Rvalue' do use indirection since those members represent memory content. In this case, the
'Rname' macro could be simplified to '(s)'.
This method of simulating structures involves a little more work than actual structures do, since you have
to code the offset to each member. It does however allow you to insure that each member is placed EXACTLY where you
wish in the structure. You can also overlap members (fully or partially), creating "unions". Since you can do this on a member by member basis, you
have great flexibility in creating combination structure/unions that you could not easily define with the standard 'C' syntax.
If you use this technique on a processor that requires word alignment, you must be careful to insure that all structures and members are aligned properly.
|
|