Difference Between Typedef and Macro in C
Introduction
In any programming language, including C, there exists a set of reserved keywords, such as typedef, that cannot be utilized as variable names. These keywords hold special meanings and play a crucial role in the language syntax.
In C programming, the keyword typedef introduces a unique feature. Additionally, C offers another powerful tool known as macros. If you’re acquainted with C programming, you might initially perceive typedef and macros as similar or even identical.
However, the reality is that typedef and macros differ significantly. This blog post aims to explore the distinctions between them, starting with the fundamentals. Whether you’re new to these concepts or seeking a deeper understanding, we’ll dissect the differences practically through illustrative examples.
What is Typedef ?
Typedef is a keyword which is used for creating alias names for any datatype.
Generally, typedef in c is used with user defined datatypes like structures and unions. This is mainly because usage of datatypes gets a bit complicated while implementing in code.
Let us understand a use case of typedef used with structure.
Example:
Output :
In the above example, in line 4 structure employee is used along with typedef and given an alias name as record. This alias becomes a new data type.
Instead using the entire structure name using typedef makes the code simple and easier to read and maintain. An example snippet is given below. With this hope you are able to build an initial understanding of typedef and its benefit of using it in C programming.
Now that we have built a basic idea, let us move on and understand what Macros are all about.
What are Macros ?
Macro is a fragment of code, where a name is associated with it. Whenever a defined macro (name) is called in a program, it will be replaced with the fragment of code defined within the macro. Also note this code replacement happens during the pre-processor stage itself which is the first phase of compilation of a C program.
Preprocessors are not aware of the keywords. This means, 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 the find and replace rule, thus avoiding any function calls overhead. Similar to typedef in c, macros also improve code readability.
Let us see an example to understand macros better.
Example:
Output :
In the above given example, MAXIMUM is a macro defined in line 2 to find the greatest number among the two given numbers. When a 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.
Difference 1 - Variable Declaration
Declaration of variables using typedef in c and macros may seem similar.
But the reality is different. To understand variable declaration using typedef and macros, let us go through an example given below.
Let us consider a simple snippet given below, which has both typedef and macro.
In the initial section, a character pointer (basically char *) is type casted as ptr. In the similar lines a macro PTR is created which will substitute a character pointer.
Subsequently in line 7, three variables declared, var1 ,var2 and var3 as character pointer variables typedef.
Now, let us consider the macro PTR. Similar to typedef we declare another three variable var4, var5 and var6 in line 11.
Example:
When we try to print the size of all the variables declared using both typedef and macros, we get a different output than what we expected.
As you can see in the below output, all the variables declared using typedef are printing the correct value of 8 (64 bit address) for all the pointer variables var1, var2 and var3. This is as per our expectation.
On the other hand among all the variables declared using macros, only var4 is having the correct value. Variables var5 and var6 are still printing the value of 1 byte, which is not expected.
Output:
Let us try to understand this better.
In case of typedef the statement
ptr var1, var2, var3 gets expanded as
char* var1;
char* var2;
char* var3;
Whereas in case of Macros,
PTR var4, var5 ,var6 gets expanded as
char * var4;
char var5;
char var6;
This is mainly because the macro substitution happens at the pre-processor level, which is not as intelligent as the compiler. So it applies the pointer property only to the var4 and
keeps var5 and var6 as simple character variables.
On the contrary typedef substitution happens during compilation stage, where it applies pointer property to var1, var2 and var3 thereby getting expected output.
Difference 2 - Scope Rule
Going by the definition, A scope is a region of the program. The scope of variables refers to the area of the program where the variables can be accessed after its declaration. Outside this region, the variable cannot be accessed. It will be treated as an undeclared identifier.
Handling variable scope becomes important when there are more lines in the program. The typedef always follows scope rules whereas macros doesn’t. This results in some unexpected output in C programs.
Let us try to understand this with some snippets.
Example:
Output :
Consider the example given above.
The 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. This is expected because NUM here works like a global variable.
When NUM is redefined to 100 with a new block in line 9 and when we try to print NUM within the scope in line 10, we obtain 100 as the result. This is also expected behavior because here NUM is overridden with a local scope within the new block.
Now watch carefully, when we try to print the value of NUM once again in line number 12, the value that is printed is again 100 not 50. This is not an expected behavior.
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, causing side effects in the code.
When it comes to typedef, such side effects won’t happen. It works as per the scope rules.
Example :
Output :
To understand the typedef scope rule, let us consider the example given above.
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 the print statement (line 6) gets executed, the character stored in t1 gets printed.
Now if we have to declare an integer variable within a scope, we can typedef int and provide the 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.
Difference 3 - Stringizing
In a 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 parameters 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 the end of the parameter list and comma is a delimiter.
This stringizing cannot be done by using typedef. We can only give names to other types. We cannot pass value or any symbol to typedef. It does not replace any text.
Example:
Output:
Difference 4 - Arguments Passing
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.
Similarly 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 the difference between typedef and macro in c.
Example:
Output :
Conclusion
In this blog post, we delved into the intricate difference between typedef and macro in c. These distinctions, while subtle, play a significant role in the way developers structure their programs.
We saw the differences with respect to Variable declaration, Scope rule, Stingizing and Arguments handling. While both typedef and macros enhance code readability, they serve distinct purposes in the C programming landscape. Typedef simplifies the handling of user-defined data types, making code more comprehensible.
Macros, on the other hand, provide powerful tools for code manipulation during the preprocessor stage, enabling dynamic string generation and logical computations.
Understanding when and how to leverage typedef and macros empowers programmers to write more efficient and maintainable C code. By grasping these differences, you can develop better code especially in domains like Embedded Systems.
SN | Related Blogs | Links |
---|---|---|
1 | Enumeration in C | Click Here |
2 | Why is C the most preferred language for Embedded Systems? | Click Here |
3 | Sizeof operator in C – A practical tutorial | Click Here |
People Also Ask (PAA)
Typedef improves code readability by allowing you to create custom, descriptive names for data types. For example, you can typedef “struct Student” to “StudentType,” making your code more self-explanatory and easier to understand.
No, macros cannot be used to create custom data types like typedef. Macros are text substitution mechanisms and don’t have the type-safety and semantic richness that typedef offers.
Common use cases for macros in C include defining constants (e.g., #define PI 3.14159), creating inline functions or code snippets, and conditional compilation (e.g., #ifdef and #ifndef for platform-specific code).
Yes, there are limitations to using macros. Macros lack type-checking, which can lead to subtle bugs in your code. They are also not very readable, and debugging macro-related issues can be challenging. Additionally, macros can’t create new data types like typedef.