# Various software sizes calculation

Andrei Chichak groups at chichak.ca
Sun Oct 11 06:38:09 UTC 2009

```On 2009-October-10, at 8:19 PM, Aaron J. Grier wrote:

> On Tue, Oct 06, 2009 at 11:05:21AM +0200, Thomas Doerfler wrote:
>> But in various applications size matters. So if you have let's say
>> 128KByte of RAM in your (space?) system and you need an answer to the
>> question "which data types might be appropriate if I want to save an
>> array of 16000 measured data samples" then getting this information
>> may be quite important. ok?
>
> isn't this what the stdint.h types are for?  uint32_t, int8_t, etc.

Sorry to chime in, but ABSOLUTELY! One of the basic MISRA guidelines
for the use of the C language in safety critical systems is that you
never use the base types of the C language. The size is processor and
compiler implementation dependant.

The standard trick question is "How many bits is an 'int' in C?"
Answer: an int is the natural size of the processor. So on a Microchip
PIC I found out, the hard way, that an int is 8 bits, but that depends
on which family of PIC. On an HC12 it is 16 bits. A CDC Cyber is 60
bits. Etcetera. Only the compiler writers know how big an int might be
on an Intel core duo, 32 or 64.

One of my standard things is to define, and check the size of, CHAR,
BOOLEAN, INT8U, INT8S, INT16U, INT16S, INT32U, INT32S, INT64U, INT64S,
FP32 and FP64, with code like:

typedef unsigned char	BOOLEAN;
typedef unsigned char	INT8U;			/* unsigned 8 bit quantity */
typedef signed char	INT8S;			/* signed 8 bit quantity */
typedef unsigned short	INT16U;			/* unsigned 16 bit quantity */
typedef signed short	INT16S;			/* signed 16 bit quantity */
typedef unsigned int	INT32U;			/* unsigned 32 bit quantity */
typedef signed int	INT32S;			/* signed 32 bit quantity */
typedef float		FP32;			/* Single precision floating point quantity */
typedef double		FP64;			/* Double precision floating point quantity */

typedef char		CHAR;

that way there is no question about size. And to check:

static const union {
INT8U int8u_t_incorrect[(INT32U) sizeof(INT8U) == 1];
INT8U int8s_t_incorrect[(INT32U) sizeof(INT8S) == 1];

INT8U int16u_t_incorrect[(INT32U) sizeof(INT16U) == 2];
INT8U int16s_t_incorrect[(INT32U) sizeof(INT16S) == 2];

INT8U int32u_t_incorrect[(INT32U) sizeof(INT32U) == 4];
INT8U int32s_t_incorrect[(INT32U) sizeof(INT32S) == 4];

INT8U fp32_t_incorrect[(INT32U) sizeof(FP32) == 4];
INT8U fp64_t_incorrect[(INT32U) sizeof(FP64) == 8];
} typeChecker;

This will cause a compile time error if the sizes are not as expected.

uint32_t and such only came around in C99 and still aren't being
adopted by the industry. C# actually discourages such things right in
their style guidelines, preferring to use ints (but then again they
also prefer not to put braces around single line ifs...dangerous
habits).

Also, int8_t doesn't explicitly indicate its signedness, it is still
open to interpretation. I can never remember the signedness of an int,
which also determines their range. I think it is best to be explicit.

I was doing some timing tests earlier. It was quite amazing how slow
software floating point is. It takes about 24 times as much time as a
scaled integer equivalent (MCF5282). On the other hand there wasn't a
huge difference between multiply and addition times on the same type.
32 bit ops were a bit quicker than 16 bit and quite a bit faster than
8 bit. You could gain a bunch of performance by using a data type that

You might not want to store 16000 32 bit numbers because they are
faster in calculations, even though you only need 16 bits, but you may
want to investigate using 32s in your calculations.

Also watch for padding when dealing with structs and simple variables,
put your largest data elements (INT32[US]) first, leaving the byte
size stuff till the end. Compilers will throw in extra bytes that
never get used to get the alignment correct.

32s usually have to be longword aligned (address % 4 == 0), 16s word
aligned (even address only), and 8s can be anywhere. An 8 followed by
a 32 may have 3 bytes of filler so that the 32 will be aligned
properly. Without keeping this in mind, your structs may be larger
than the sum of their parts, your heaps fragmented, and stacks may
take up more space than you think. Check your map file if space is
tight.

Basically you have to watch the size and signedness of your data,
match them to the processor, and arrange them so they don't make
filler holes.

Andrei
---------------------
Andrei Chichak

Systems Developer
CBF Systems Inc.
4-038 NINT Innovation Centre
Edmonton, Alberta