Emertxe-News & Blog

Home » C » Difference between typedef and macro in C
Difference between typedef and macro in C

Introduction

In any programming language, there are a set of keywords available, which can’t be used as variable name. It is because keywords are reserved and they have a special meaning. Keywords which are also called as reserved names can be anything like a command or parameters etc. In C programming, there is a keyword called “typedef” and here in this blog we will be learning the difference between typedef and macros. Macros are defined using “#define”, one of the preprocessor directives available in C programming.

First, let us understand what is typedef and macro which will help in learning the difference between typedef and macro in c.

Typedef

typedef is a keyword which is used for creating alias name for any datatype. Generally, typedef is used with user defined datatypes, when names of datatype get a bit complicated to use in programs. Here is an example of typedef with structure.

Example

1   #include <stdio.h>
2   #include <string.h>
3
4   typedef struct employee
5   {
6       int id;
7       char name[30];
8   }record;                //structure employee is typedefed to record
9
10  int main()
11  {
12       record employee_info;
13       employee_info.id=1;
14       strcpy(employee_info.name, "Aravindh");
15       printf(" Employee ID is: %d \n", employee_info.id);
16       printf(" Employee Name is: %s \n", employee_info.name);
17       return 0;
18  }

Fig 1: Example explaining typedef

Output

difference between typedef and macro in c

Fig 2: Output image of typedef example

In the above example, in line 4 structure employee is typedefed and alias name is given as record line 8. Now, we can declare a variable to the structure using “record” and also it can be used to access the structure members.

Macros

Macro is a fragment of code, where name is given to it. Whenever a defined macro (name) is called in a program, it will be replaced with the fragment of code defined within the macro. Except the preprocessor operator ”defined”, any valid identifier including keywords can be defined as a macro. It is because the preprocessor is not aware of the keywords. Macros can be anything, it can be a code block, loops or function calls etc. Macros are majorly used when performance is the priority. It is because macros follow find and replace rule, thus avoiding any function calls overhead. Let us see an example to understand macros better.

Example

1 #include <stdio.h>
2 #define MAXIMUM(a,b) ((a) > (b) ? (a) : (b)) // Macro defined
3 
4 int main()
5 {
6    printf("Biggest number among the two is %d\n", MAXIMUM(50,25)); 
7    return 0;
8 }

Fig 3: Example explaining macros

Output

difference between typedef and macro in c

Fig 4: Output image of macros example

In the above given example, MAXIMUM is a macro defined in line 2 to find greatest number among the two given numbers. When preprocessor encounters MAXIMUM in the program, it replaces the content of that macro there (macro expansion). Later the evaluation part takes place.

Now that we have understood basic usage of typedef and macros, we will try to understand the difference between them as a part of this blog post.

Differences

Variable Declaration

Declaration of variables using typedef and #define may seem similar. But the reality is different. To understand variable declaration using typedef and macros, let us go through an example given below.

Example 1

In the below given example1, ptr (typedefed) is the synonym of char * in line 2. When we require pointer variables of type char, we can declare the variables using synonym “ptr”. In line 7 all three variables declared, var1 ,var2 and var3 are pointer variables. This is helpful when we have to declare more pointer variables together.

Now let us consider the macro PTR. PTR is the macro name for char * as defined in line 3. Whenever preprocessor hits PTR in the code, it replaces PTR with char *. Here in this example, we are declaring 3 variables, var4, var5 and var6 line 11 which will be expanded as,

char * var4,var5,var6; which is further expanded as,

char * var4;
char var5;
char var6;

When we try to declare pointer variables using macro, declaration purpose is not achieved. Only var4 is declared as pointer variable of type char. Other two variables var5 and var6 are declared as just character variables not pointers.

This can be observed from the output of the program, where sizeof var1,var2,var3 and var4 are same 8 bytes and sizeof var5 and var 6 are 1 byte each. Hence declaration can be made simple using typedef whereas it fails when macros are involved.

1 #include<stdio.h>
2 typedef char *ptr;                    //char * is typedefed to ptr
3 #define PTR char*                   // PTR is a macro to char *
4
5 int main()
6 {
7     ptr var1,var2,var3;
8
9     printf("size of var1 = %d\nsize of var2 = %d\n
             size of var3 = %d\n",sizeof(var1),sizeof(var2),sizeof(var3));
10
11    PTR var4,var5,var6;
12
13    printf("size of var4 = %d\nsize of var5 = %d\n
             size of var6 =  %d\n",sizeof(var4),sizeof(var5),sizeof(var6));
14 }

Fig 5: Example 1 explaining variable declaration using typedef and macro

Output

difference between typedef and macro in c

Fig 6: Output image of example1

Example 2

Considering another example to understand the variable declaration using typedef and #define. Here, PTR1 is defined as a macro in line 2. A constant variable declaration is done using PTR1 in line 8.

const PTR1 myptr1 is expanded as const char * myptr1, which is a simple textual replacement. Whereas ptr2, which is a synonym (typedefed in line 3) of char *, is declared as char * const ptr2. This shows typedef is not a textual replacement. Thus when we try to assign NULL value to myptr2 in line 12, it fails. We can see the error from output that, assignment of read-only variable myptr2, meaning we can’t write to myptr2 since it is a constant.

1 #include<stdio.h>
2 #define PTR1 char*
3 typedef char * ptr2;
4
5 int main()
6 {
7    char x;
8    const PTR1 myptr1 = &x;
9    const ptr2 myptr2 = &x;
10
11    myptr1 = NULL;
12    myptr2 = NULL;
13
14 }

Fig 7: Example 2 explaining variable declaration using typedef and macro

Output

difference between typedef and macro in c

Fig 8: Output image of example 2

Example 3

typedef has the capability of creating new types which is far superior to #define. We can have types defined as given in the example below. Here, func_type is defined of type void(*) () (line 2). It is a pointer to function with return type void which takes no arguments.

1 #include<stdio.h>
2 typedef void(*func_type) ();
3 int main()
4 {
5    func_type myptr;
6    myptr = clrscr;
7 }

Fig 9: Example explaining variable declaration using typedef

Example 4

Also we can have synonym for unsigned int, short int datatypes defined using typedef. We cannot have types defined with typedef along with the modifiers like,

typedef int data;

short data type;

Compiler throws an error. This is because, types defined using typedefs are treated as special types by compiler. These are not textual replacement like macros. Hence, the correct way of defining it as,

typedef int data;

typedef short data datatype;

datatype newtype;

where, newtype is of type short int.

Scope Rule

Scope rules are very important when there are more number of lines in the program. If we are using same macro or typedef which is required only within the scope, we should ensure it is within that scope. Let us understand it with the help of examples.

typedef always follows scope rules whereas macros doesn’t obey any scope rule. This may result in error or unexpected output. Here are some examples to understand it better.

Macro and scope rule

Considering the example given below, where a macro NUM is defined in line 2 which holds integer 50. When macro is called inside main in line 6 we could observe that integer 50 is getting printed. When NUM is redefined to 100 without doing any #undef operation in line 9 and when we try to print NUM within the scope in line 10, we obtain 100 as the result.

Once if statement is executed, print statement (line 12) outside scope (if) gets executed. The value that is printed is again 100 not 50. This means that, 100 is replaced in the place of 50, even when 50 is not undefined inside scope. Thus macro doesn’t obey any scope rule.

Example

1 #include <stdio.h>
2 #define NUM 50
3 
4  int main()
5 {
6    printf("Number is %d\n",NUM);
7    if(NUM)
8   {
9       #define NUM 100
10     printf("Number inside scope is %d\n",NUM);
11 }
12 printf("Number outside scope is %d\n",NUM);
13 return 0;
14 }

Fig 10: Example explaining scope rule using macro

Output

difference between typedef and macro in c

Fig 11: Output image of example

typedef and scope rule

To understand typedef scope rule, let us consider the example given below. In line number 4, char is typedefed and the alias name is given as “text”. A variable t1 of type char is declared and initialized with a character in line 5. When print statement (line 6) gets executed, the character stored in t1 gets printed.

Now that if we have to declare an integer variable within a scope, we can typedef int and provide same name “text” as in line number 8. By using text, we can declare and initialize the same variable t1 again, with an integer as in line 9 . The print statement (line 10) within the scope, when executed prints integer 5.

Character ‘q’ which was stored before in line 5 did not reflect within the scope. When t1 is again printed (line 12), q is got as output not 5. This means, whatever is declared within the scope did not reflect outside the scope. Thus, typedef obeys scope rules.

Example

1 #include <stdio.h>
2 int main()
3 {
4    typedef char text;
5    text t1 = 'q';
6    printf("character t1 is %c\n",t1);
7    {
8      typedef int text;
9      text t1 = 5;
10    printf("integer t1 is %d\n", t1);
11  }
12  printf("integer t1 is %c\n", t1);
13 }

Fig 12: Example explaining scope rule using typedef

Output

difference between typedef and macro in c

Fig 13: Output image of example

Stringizing

In few conditions, we may need to convert a macro argument to string constant. Anything can be made as string by passing it to macro with the help of stringizing operator (#). The operator is used only with the macros that take arguments. It converts macro parameter to string literals without expanding the parameter definition.

In the example given below, number, symbol and word are passed to the macro where they are converted into strings using # operator, except comma “,” and right parenthesis “)” which cannot be stringized. It is because “)” marks end of the parameter list and comma is a delimiter.

This stringizing cannot be done by using typedef. We can only give name to other types. We cannot pass value or any symbol to typedef. It does not replace any text.

Example

1 #include<stdio.h>
2 #define STRING(y) #y
3 int main()
4 {
5      printf("string 1 %s\n",STRING(100));
6      printf("string 2 is %s\n",STRING(" Embedded "));
7      printf("string 3 is %s\n",STRING("/ Emertxe /"));
8 }

Fig 14: Example explaining stringizing operator

Output

difference between typedef and macro in c

Fig 15: Output image of example

Evaluation

Macros with arguments are helpful in performing some logical calculations. We can pass a value or values to macro, which will then be replaced in the macro parameter and respective operations will be done according to the parameter. This is not possible in typedef.

In the example, PRINT is a macro containing printf statement in line 2, when called (line 11), it will substitute printf statement in the program and print the statement given within. CALCULATE macro (line 3) holds some mathematical calculation, when values are passed to the macro, substitution is done and finally the calculated value gets stored in variable calc in line 9.

We can use typedef and reduce complexity in declaration of complex datatypes. We cannot perform any calculations using typedef. This is how macros differ from typedef.

Example

1  #include<stdio.h>
2  #define PRINT printf("Welcome to Emertxe")
3  #define CALCULATE(a,b) ((a+b)*(a-b))
4  int main()
5  {
6       int x,y,calc;
7       printf("Enter the values of x and y\n");
8       scanf("%d %d",&x,&y);
9       calc = CALCULATE(x,y);
10      printf("%d\n",calc);
11      PRINT;
12 }

Fig 16: Example explaining evaluation done using macro

Output

difference between typedef and macro in c

Fig 15: Output image of example

Conclusion

The other differences between typedef and #define are,

  • We can have symbolic names to datatypes using typedef but not to numbers etc. Whereas with a macro, we can represent 1 as ONE, 3.14 as PI and many more.
  • We can have a type name and a variable name as same while using typedef. Compiler differentiates both.
  • When we declare a local-scope identifier by the same name as typedef, we should provide type name explicitly. Otherwise compiler will give an error.

Thus, when it comes to performance, we can use macros which will help in avoiding function call overhead and when it comes to avoiding complex declarations in a big program, we can make use of typedef.

Best Embedded systems training institute with placements in Bangalore.

YOU MAY ALSO LIKE

Online Free IoT Internship for Engineering Students – 2023

Online Free IoT Internship for Engineering Students – 2023

The Internship Ecosystem An internship is a type of professional learning opportunity where engineering students get practical work related to their field of study or career interest. Through an internship, a student can explore and advance their career while...

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *