It's often done for code portability, and is particularly relevant for embedded systems.
Suppose you have some integer values that absolutlely MUST be 32-bits long. Maybe they need to map to network/disk structures, maybe they need to hold values of that magnitude, or whatever.
Now, suppose you develop your code on a compiler where 'int' is 32 bits. You write...
struct s {
int a,b,c,d;
}
...and it works fine. But, if you need to switch to a compiler where int is only 16-bits, but long is 32, you would need to change all those declarations to
struct s {
long a,b,c,d;
}
Worse yet, you can't do just search/replace, because some of the 'ints' you probably don't care about the size. So, the best approach is to to this:
typedef long INT32; // change this typedef according to compiler
struct s {
INT32 a,b,c,d;
}
Then, all you need to is change the typedefs.