The easiest way is to use ptype with gdb.
Example:
foo.c
#include <sys/types.h> struct st { int i; char c; }; typedef int Array[10]; typedef struct st St; int main(void) { size_t s1; ssize_t s2; pid_t pid; Array arr; St st1; return 0; }
$ gcc -Wall -g -o foo foo.c $ gdb foo (gdb) b main (gdb) run (gdb) ptype s1 type = long unsigned int (gdb) ptype size_t type = long unsigned int (gdb) ptype s2 type = long int (gdb) ptype ssize_t type = long int (gdb) ptype pid type = int (gdb) ptype pid_t type = int (gdb) ptype arr type = int [10] (gdb) ptype Array type = int [10] (gdb) ptype st1 type = struct st { int i; char c; } (gdb) ptype St type = struct st { int i; char c; }
Like the above example,
ptype <expression or type name>
shows real type.
If the type is an array, it also shows its size. If the type is a struct, it also shows the type of the members of the struct. It's convenient.
You can probably find the real type using gcc -E option and looking into preprecessor's output like below, but it's bothersome and possibly needs hard work.
$ gcc -E foo.c | grep ssize_t typedef long int __ssize_t; typedef __ssize_t ssize_t; (ommitted below)
In the above example (x86_64 GNU/Linux), you can find that ssize_t is
__ssize_t => long int
$ gcc -E foo.c | grep ssize_t typedef long __darwin_ssize_t; (ommitted) typedef __darwin_ssize_t ssize_t; (ommitted)
In the above example (Mac OS X), you can find that ssize_t is
ssize_t => __darwin_ssize_t => long