One small fix and the explanation of Stringizing and Token Pasting Operators that can be used effectively in C macros.
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| title: Macros in C
 | |
| ---
 | |
| ## Macros in C
 | |
| 
 | |
| A macro is a piece of code with a given name. When the name is used, it is replaced by the content of the macro. The `#define` keyword is used to define new macros. It's followed by a name and a content. By convention, macro names are written in uppercase. There are two type of macros: `Object-like` macros and `Function-like` macros.
 | |
| 
 | |
| #### Object-like Macros
 | |
| ```C
 | |
| #define PI 3.14
 | |
| ```
 | |
| 
 | |
| If you use the macro this way:
 | |
| ```C
 | |
| printf("Value of PI: %d", PI);
 | |
| ```
 | |
| Is the same as write this:
 | |
| ```C
 | |
| printf("Value of PI: %d", 3.14);
 | |
| ```
 | |
| #### Undefining Macros
 | |
| After defining macros you can also undefine them at any point.
 | |
| just Type
 | |
| ```C
 | |
| #undefine PI
 | |
| ```
 | |
| This is used to use macros only for specific lines of code and again undefine it.
 | |
| 
 | |
| #### Function-like Macros
 | |
| Function-like uses the same `#define` keyword. The difference is that you use a pair of parentheses after the function name.
 | |
| ```C
 | |
| #define hello_world() printf("Hello World!")
 | |
| ```
 | |
| 
 | |
| So calling:
 | |
| ```C
 | |
| hello_world();
 | |
| ```
 | |
| 
 | |
| You get:
 | |
| ```C
 | |
| printf("Hello World!");
 | |
| ```
 | |
| 
 | |
| You can set parameters too:
 | |
| ```C
 | |
| #define hello(X) printf("Hello " X "!")
 | |
| ```
 | |
| 
 | |
| Now calling:
 | |
| ```C
 | |
| hello("World");
 | |
| ```
 | |
| 
 | |
| You get the equivalent of:
 | |
| ```C
 | |
| printf("Hello World!");
 | |
| ```
 | |
| 
 | |
| #### Special Operators in Macros
 | |
| One can use the special operators # (stringize) and ## (concatenate) in macros for achieving unique functionality.
 | |
| 
 | |
| ##### Stringizing Operator (#)
 | |
| A macro's parameter preceded by a `#` is converted and treated as a string token.  
 | |
| For example, we can define ERROR and WARN macros that print a LOG message.  
 | |
| While the LOG message gets prefixed with either an `ERR` or a `WARN`, respectively.
 | |
| ```C
 | |
| #define LOG(level, message) printf(#level ": " #message "\n")
 | |
| #define ERROR(msg) LOG(FAIL, msg)
 | |
| #define WARN(msg) LOG(WARN, msg)
 | |
| ```
 | |
| 
 | |
| Now, one can use it as
 | |
| ```C
 | |
| ERROR(Invalid settings);  // Output-> FAIL: Invalid settings
 | |
| WARN(Upper threshold);    // Output-> WARN: Upper threshold 
 | |
| ```
 | |
| 
 | |
| ##### Concatenation (or token-pasting) Operator (##)
 | |
| Using concatenation the parameters can be joined together to form one single token. Token-pasting is much more powerful in the sense that the resulting token could be an object defined in the C program. 
 | |
| ```C
 | |
| #define NUM(x) number_##x
 | |
| 
 | |
| void foo() {
 | |
|   int number_one = 10;
 | |
|   int number_two = 15;
 | |
| 
 | |
|   printf("%d + %d = %d\n", NUM(one), NUM(two), NUM(one) + NUM(two));
 | |
|   // Output-> 10 + 15 = 25
 | |
| }
 | |
| ```
 | |
| 
 | |
| #### More Information:
 | |
| - [GCC Online Documentation: Macros](https://gcc.gnu.org/onlinedocs/cpp/Macros.html)
 | |
| - [GCC Online Documentation: Object-like macros](https://gcc.gnu.org/onlinedocs/cpp/Object-like-Macros.html#Object-like-Macros)
 | |
| - [GCC Online Documentation: Function-like macros](https://gcc.gnu.org/onlinedocs/cpp/Function-like-Macros.html#Function-like-Macros)
 |