Are typedef and #define the same in c?

I wonder if typedef and #define are the same in c?


Solution 1:

typedef obeys scoping rules just like variables, whereas define stays valid until the end of the compilation unit (or until a matching undef).

Also, some things can be done with typedef that cannot be done with define.
For example:

typedef int* int_p1;
int_p1 a, b, c;  // a, b, c are all int pointers

#define int_p2 int*
int_p2 a, b, c;  // only the first is a pointer, because int_p2
                 // is replaced with int*, producing: int* a, b, c
                 // which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c;  // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp;  // func_p is a pointer to a function that
            // takes an int and returns an int

Solution 2:

No.

#define is a preprocessor token: the compiler itself will never see it.
typedef is a compiler token: the preprocessor does not care about it.

You can use one or the other to achieve the same effect, but it's better to use the proper one for your needs

#define MY_TYPE int
typedef int My_Type;

When things get "hairy", using the proper tool makes it right

#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);

void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */

Solution 3:

No, they are not the same. For example:

#define INTPTR int*
...
INTPTR a, b;

After preprocessing, that line expands to

int* a, b;

Hopefully you see the problem; only a will have the type int *; b will be declared a plain int (because the * is associated with the declarator, not the type specifier).

Contrast that with

typedef int *INTPTR;
...
INTPTR a, b;

In this case, both a and b will have type int *.

There are whole classes of typedefs that cannot be emulated with a preprocessor macro, such as pointers to functions or arrays:

typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20]; 
...
CALLBACK aCallbackFunc;        // aCallbackFunc is a pointer to a function 
                               // returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
                               // returning a pointer to a 20-element array
                               // of pointers to int

Try doing that with a preprocessor macro.

Solution 4:

#define defines macros.
typedef defines types.

Now saying that, here are a few differences:

With #define you can define constants that can be used in compile time. The constants can be used with #ifdef to check how the code is compiled, and specialize certain code according to compile parameters.
You can also use #define to declare miniature find-and-replace Macro functions.

typedef can be used to give aliases to types (which you could probably do with #define as well), but it's safer because of the find-and-replace nature of #define constants.
Besides that, you can use forward declaration with typedef which allows you to declare a type that will be used, but isn't yet linked to the file you're writing in.