C++ Constant Expressions Vs Macros
C++ Constant Expressions Vs Macros
In this post, we will discuss C++ Constant Expressions( const expr) and how they replace traditional Macros(#define).
- Macros in C/C++
- Macro is a Preprocessor directive in C/C++ used to define expressions with names.
- Before compilation, the Preprocessor will search for the name in the entire code and replace it with the expression.
- Below is an example of how to define a macro identifier with a value
#include<stdio.h> //here are defining a macro #define PI 3.14 int main() { int radius = 5; /* * In the below code Preprocess replace PI with 3.14 before compilation */ int area_of_circle = PI*radius*radius; printf("Area is : %d\n",area_of_circle); int perimeter = 2*PI*radius; printf("Perimeter is : %d\n\n",perimeter); return 0; }
#include<stdio.h> //her are defining a macro expression #define GREATER(x,y) (x > y ? x :y) int main() { int radius = 5; /* * In below code Preprocess will replace GREATER(a,b) with (a > b ? a :b) before compilation. */ int a = 100; int b = 509; printf("greater among %d, %d is %d \n", a,b, GREATER(a,b)); return 0; }
1.1 Problems with Macros
- As we know Preprocessor will replace all occurrences of Macro with expression/value blindly, which will lead to compile errors or runtime errors.
- Macros are also insecure, because text replacement may lead to malicious code that can corrupt the system on which it is running.
- Check the below code which is an example of issues with Macro. Read the comments inside the code to understand better.
#include <stdio.h> // Define a Structure struct MyStruct { int data1; short data_short; char letter; }; //Define a Macro used to declare pointers to MyStruct. //When the Preprocessor finds the string "MY_STRUCT_PTR" it will be replaced by the string "struct MyStruct*" #define MY_STRUCT_PTR struct MyStruct* int main() { struct MyStruct data = {.data1 = 100, .data_short = 10, .letter ='x'}; /* * In the below line we want to create 2 pointers of struct MyStruct * But after Preprocessor replace macro name "MY_STRUCT_PTR" with expression "struct MyStruct*", * the final declaration will look like this below * MY_STRUCT_PTR data1, data2; --------> struct MyStruct *data1, data2; * We can observe the "data1" is pointer but "data2" is normal object */ MY_STRUCT_PTR data1, data2; data1 = &data; // In the below line we will get a compile error because we are assigning a normal object to a pointer data2 = &data; return 0; }
2. Constant Expressions in C++
- Constant expressions are introduced in C++11
- We can define variables and expressions with Constant expressions that are evaluated at the time of compilation.
- Like Macros there will be no memory allocated for Constant expressions.
- Constant expressions are also like variables or functions in C++
- Unlike Macros there will be no text replacement mechanism used to evaluate Constant expressions. Hence there will be no hazards of unexpected compile or runtime errors.
- There are 2 types of Constant expressions
- Constant expression variables
- Constant expression functions
2.1 Constant expression variables
- We can declare constant expression variables so that the compiler will replace all occurrences of variable names in code with their value.
- Below is an example for constant expression variables, read comments inside the code for better understanding.
#include <iostream> //define a constant expression for a packet lengths constexpr int header_length = 10; constexpr int footer_length = 2; constexpr int payload_length = 2; constexpr int total_pkt_length = header_length + footer_length + payload_length; int main() { /* * In the below code "total_pkt_length" value will be computed at compile time and the resultant * expression will be like below * char packet[14] = {0}; */ char packet[total_pkt_length] = {0}; return 0; }
2.2 Constant expression functions
- Constant expression functions will be evaluated at compile time to return a result.
- Compiler will replace all occurrences of function names in the code with its corresponding return value.
- We can't pass normal variables as arguments while calling a constant expression function. Only variables declared as constexpr are allowed.
- After C++14 it is allowed to pass normal variables as arguments but then the function will converted to a normal inline function.
- Below is an example of a constant expression function, read comments inside the code for better understanding.
#include <iostream> using namespace std; /* * Below is the Constant expression function that converts temperature in Fahrenheit to Celsius * Call to this function will be evaluated at runtime and replaced with the returned value */ constexpr int convert_fh_to_celsius(const int &temp_fh) { return (temp_fh - 32)*5/9; } int main() { constexpr int min_temp_in_fh = 50; /* * In the below code function "convert_fh_to_celsius" will called at compile time and return value will be replaced. * Below statement will be converted as * cout<<"Minimum temperature in celsius: "<<10<<endl; * 50 degree Fahrenheit is 10 degree in Celsius */ cout<<"Minimum temperature in celsius: "<< convert_fh_to_celsius(min_temp_in_fh)<<endl; constexpr int max_temp_in_fh = 120; /* * Same as above below statement will be coverted as * cout<<"Maximum temperature in celsius: "<< 48<<endl; * 100 degree Fahrenheit is 48 degree in Celsius */ cout<<"Maximum temperature in celsius: "<< convert_fh_to_celsius(max_temp_in_fh)<<endl; return 0; }
Thanks for the great info and its easy to understand
ReplyDelete