Here is one rationale for using a
typedef.
Consider the following example for a struct to be used in analyzing stock market data:
1 2 3 4 5 6 7 8 9
|
struct PriceBar
{
date d;
double open;
double high;
double low;
double close;
unsigned long volume;
};
|
Let's assume you have written multiple functions spread over multiple programs that use the
PriceBar struct. Perhaps you have a function, one of whose parameters is the share volume, say
myFunction( unsigned long numberShares, ... )
If
pb is a price bar you might be calling the function like so
myFunction( pb.volume, ... );
Now the stock market is booming and you suddenly realize that volume may no longer fit in 32-bit unsigned long, so change the
PriceBar struct and make volume a unsigned long long (64-bits).
1 2 3 4 5 6 7 8 9
|
struct PriceBar
{
date d;
double open;
double high;
double low;
double close;
unsigned long long volume;
};
|
The call to
myFunction above will now fail because when passing it
pb.volume the function is expecting a 32-bit unsigned int but
pb.volume is a 64-bit unsigned int so the parameter will be cut down to 32-bits resulting in possible data loss and incorrect evaluation in the function. It will be necessary to look through all functions and programs using
PriceBars, changing code as necessary, a time consuming and error prone process. Failure to do so could result in subtle bugs where incorrect results are being computed and it may not be obvious that the results are incorrect.
Now suppose instead we had used a typedef as follows:
1 2 3 4 5 6 7 8 9 10 11
|
typedef share_volume unsigned long;
struct PriceBar
{
date d;
double open;
double high;
double low;
double close;
share_volume volume;
};
|
and that we had used s
hare_volume throughout are code. So in
myFunction we would have written
myFunction( share_volume numberShares, ... )
We can make the simple change
typedef share_volume unsigned long long;
Recompile all code and we are done.