Monday, March 26, 2012

typedef vs #define in C

typedef:
  • Handled by the compiler itself.
  • An actual definition of a new type (some people said adding new alias).
  • typedef obeys scoping rules just like variables.
  • The type defined with a typedef is exactly like its counterpart as far as its type declaring power is concerned BUT it cannot be modified like its counterpart. For example, let’s say you define a synonim for the int type with:
typedef int MYINT
//Now you can declare an int variable either with
int a;
//or
MYINT a;
//But you cannot declare an unsigned int (using the unsigned modifier) with
unsigned MYINT a;
//although
unsigned int a;
//would be perfectly acceptable.
  • typedefs can correctly encode pointer types.
  • Some things can be done with typedef that cannot be done with define. Examples:
typedef int* int_p1;
int_p1 a, b, c;  // a, b, and c are all int pointers.

#define int_p2 int*
int_p2 a, b, c;  // only the first is a pointer!
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
#define:
  • Handled by the preprocessor (a program run before actual compiler).
  • Works like replacing all in your editor.
  • #DEFINES are just replacements done by the preprocessor. For example:
  1. typedef char *String_t;
  2. #define String_d char *
  3. String_t s1, s2; String_d s3, s4;
s1, s2, and s3 are all declared as char *, but s4 is declared as a char, which is probably not the intention.
  • #define stays valid until the end of the file (or until a matching undef).
  • A #define is just a macro, i.e. it will be processed/expanded by the preprocessor.

To summarize the main differences:
The #define directive can be used to define types, such as:
#define INT32 long int /* 32 bit signed integer type */
The typedef clause can be used in a similar manner.
typedef long int int32; /* 32 bit signed integer */

The typedef is preferred over the #define because is better integrated into the C language, and it can create more kinds of variable types than a mere define.

Consider the following:
#define INT_PTR int    /* Define a pointer to integer */
typedef int *int_ptr;  /* Define a pointer to an integer */
INT_PTR ptr1, ptr2;    /* This contains a subtle problem */
int_ptr ptr3, ptr4;    /* This does not */
What's the problem with the line INT_PTR ptr1, ptr2 ? The problem is that ptr2 of type integer, not a pointer to integer. If you expand this line, the problem, comes apparent:
INT_PTR ptr1, ptr2;    /* This contains a subtle problem */
int *  ptr1, ptr2;     /* This contains a subtle problem */
Problems like this can be avoided by using typedef .
When possible, use typedef instead of #define .

No comments:

Post a Comment