Array typedef vs. structure

  • Thread starter Thomas Matthews
  • Start date
T

Thomas Matthews

Hi,

I'm writing code for an embedded system. In the system a
Timer has 4 memory mapped registers of 32-bit lengths
in contiguous locations:
Timer 0:
0x1000 Configuration register
0x1004 Control register
0x1008 Input register
0x100C Output register.

My objective is to declare a type for the timer,
so I can write the following:
Timer * pTimers = (Timer *) 0x1000;
pTimers[1]->Config_Reg = 0x24;
/* or */
pTimer++; /* points to next timer */

My choices are to declare a typedef of an array of
4 32-bit {unsigned} integers or a structure with
4 32-bit {unsigned} integers.

Th issue with a structure is that the compiler
*may* insert padding bytes between members, which
would mess up the mapping (of members to physical
registers).

However, an array doesn't have field members, so
one would have to declare named constants for the
indices:
#define Config_Reg 0
#define Control_Reg 1
#define Input_Reg 2
#define Output_Reg 3

Is there any preference between an array typedef
and a structure for readability?

I know if I use a structure, I can always say
something like:
assert(sizeof(struct Timer) == 4 * sizeof(/* 32-bit integer */));

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
M

Mark A. Odell

Hi,

I'm writing code for an embedded system. In the system a
Timer has 4 memory mapped registers of 32-bit lengths
in contiguous locations:
Timer 0:
0x1000 Configuration register
0x1004 Control register
0x1008 Input register
0x100C Output register.

My objective is to declare a type for the timer,
so I can write the following:
Timer * pTimers = (Timer *) 0x1000;
pTimers[1]->Config_Reg = 0x24;
/* or */
pTimer++; /* points to next timer */

My choices are to declare a typedef of an array of
4 32-bit {unsigned} integers or a structure with
4 32-bit {unsigned} integers.

I use the struct version all the time in embedded systems since I don't
care so much about portability at this level. However, I also rigorously
ensure that the compiler can pack the struct such that the elements end up
at the expected locations.
 
J

Jeremy Yallop

Thomas said:
My choices are to declare a typedef of an array of
4 32-bit {unsigned} integers or a structure with
4 32-bit {unsigned} integers.

Another choice is a structure with an array of 4 32-bit unsigned ints,
which gives you both the assurance that there will be no padding and
normal C object semantics. (I doubt that there will be any padding
between 32-bit structure elements in practice, anyway.)
Is there any preference between an array typedef
and a structure for readability?

Yes. Arrays are not first-class in C, so they behave somewhat
differently to other objects. This means that a typedef for an array
is a leaky abstraction: it will be apparent to the user (of the
typedef) that the "opaque" type is really an array type. In
particular, the user will not be able to assign one instance of the
type to another and may find that a function to which such an object
is passed is able to modify the object (because the array is passed as
a pointer to the first element; if the object had struct type a copy
of the whole object would be passed as with builtin types).

Jeremy.
 
?

=?ISO-8859-1?Q?Tor_Husab=F8?=

Mark said:
Hi,

I'm writing code for an embedded system. In the system a
Timer has 4 memory mapped registers of 32-bit lengths
in contiguous locations:
Timer 0:
0x1000 Configuration register
0x1004 Control register
0x1008 Input register
0x100C Output register.

My objective is to declare a type for the timer,
so I can write the following:
Timer * pTimers = (Timer *) 0x1000;
pTimers[1]->Config_Reg = 0x24;
/* or */
pTimer++; /* points to next timer */

My choices are to declare a typedef of an array of
4 32-bit {unsigned} integers or a structure with
4 32-bit {unsigned} integers.


I use the struct version all the time in embedded systems since I don't
care so much about portability at this level. However, I also rigorously
ensure that the compiler can pack the struct such that the elements end up
at the expected locations.

Adding

assert(sizeof(Timer) == sizeof(uint32) * 4); /* four 32 bit words,
no padding allowed */

would probably a struct of four ints a safe and convenient solution.
 
?

=?ISO-8859-1?Q?Tor_Husab=F8?=

Tor said:
Mark said:
Hi,

I'm writing code for an embedded system. In the system a
Timer has 4 memory mapped registers of 32-bit lengths
in contiguous locations:
Timer 0:
0x1000 Configuration register
0x1004 Control register
0x1008 Input register
0x100C Output register.

My objective is to declare a type for the timer,
so I can write the following:
Timer * pTimers = (Timer *) 0x1000;
pTimers[1]->Config_Reg = 0x24;
/* or */
pTimer++; /* points to next timer */

My choices are to declare a typedef of an array of
4 32-bit {unsigned} integers or a structure with
4 32-bit {unsigned} integers.



I use the struct version all the time in embedded systems since I don't
care so much about portability at this level. However, I also rigorously
ensure that the compiler can pack the struct such that the elements
end up
at the expected locations.


Adding

assert(sizeof(Timer) == sizeof(uint32) * 4); /* four 32 bit words,
no padding allowed */

would probably a struct of four ints a safe and convenient solution.
....which the original poster already suggested himself. Sorry about
that one!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,781
Messages
2,569,615
Members
45,294
Latest member
LandonPigo

Latest Threads

Top